diff options
Diffstat (limited to 'src')
177 files changed, 16055 insertions, 4667 deletions
diff --git a/src/driclient/src/Makefile b/src/driclient/src/Makefile deleted file mode 100644 index 34435a2086e..00000000000 --- a/src/driclient/src/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -TARGET = libdriclient.a -OBJECTS = driclient.o XF86dri.o -DRMDIR ?= /usr - -CFLAGS += -g -Wall -fPIC -I../include -I${DRMDIR}/include -I${DRMDIR}/include/drm - -############################################# - -.PHONY = all clean - -all: ${TARGET} - -${TARGET}: ${OBJECTS} - ar rcs $@ $^ - if ! test -d ../lib; then mkdir ../lib; fi - cp ${TARGET} ../lib - -clean: - rm -rf ${OBJECTS} ${TARGET} ../lib/${TARGET} diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index ff355c47832..6cf1ddd43fe 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -142,14 +142,13 @@ C_SOURCES = \ util/u_tile.c \ util/u_transfer.c \ util/u_resource.c \ - util/u_upload_mgr.c - - # Disabling until pipe-video branch gets merged in - #vl/vl_bitstream_parser.c \ - #vl/vl_mpeg12_mc_renderer.c \ - #vl/vl_compositor.c \ - #vl/vl_csc.c \ - #vl/vl_shader_build.c \ + util/u_upload_mgr.c \ + vl/vl_bitstream_parser.c \ + vl/vl_mpeg12_mc_renderer.c \ + vl/vl_compositor.c \ + vl/vl_csc.c \ + vl/vl_idct.c \ + vl/vl_vertex_buffers.c GALLIVM_SOURCES = \ gallivm/lp_bld_arit.c \ @@ -220,3 +219,4 @@ util/u_format_table.c: util/u_format_table.py util/u_format_pack.py util/u_forma util/u_half.c: util/u_half.py $(PYTHON2) util/u_half.py > $@ +# DO NOT DELETE diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index fca7e5fd117..e6806d9a723 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -190,12 +190,11 @@ source = [ 'util/u_tile.c', 'util/u_transfer.c', 'util/u_upload_mgr.c', - # Disabling until pipe-video branch gets merged in - #'vl/vl_bitstream_parser.c', - #'vl/vl_mpeg12_mc_renderer.c', - #'vl/vl_compositor.c', - #'vl/vl_csc.c', - #'vl/vl_shader_build.c', + 'vl/vl_bitstream_parser.c', + 'vl/vl_mpeg12_mc_renderer.c', + 'vl/vl_compositor.c', + 'vl/vl_csc.c', + 'target-helpers/wrap_screen.c', ] if env['llvm']: diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv index 26a0eebc544..0ae15c9cc0a 100644 --- a/src/gallium/auxiliary/util/u_format.csv +++ b/src/gallium/auxiliary/util/u_format.csv @@ -237,3 +237,11 @@ PIPE_FORMAT_R32G32B32A32_FIXED , plain, 1, 1, h32 , h32 , h32 , h32 , xyzw, r PIPE_FORMAT_R10G10B10X2_USCALED , plain, 1, 1, u10 , u10 , u10 , x2 , xyz1, rgb # A.k.a. D3DDECLTYPE_DEC3N PIPE_FORMAT_R10G10B10X2_SNORM , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb + +PIPE_FORMAT_YV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_YV16 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_IYUV , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_NV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_NV21 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_IA44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv +PIPE_FORMAT_AI44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv diff --git a/src/gallium/auxiliary/util/u_format_yuv.c b/src/gallium/auxiliary/util/u_format_yuv.c index ab8bf29c97b..64ea0b35347 100644 --- a/src/gallium/auxiliary/util/u_format_yuv.c +++ b/src/gallium/auxiliary/util/u_format_yuv.c @@ -1045,3 +1045,138 @@ util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src, dst[3] = 1.0f; } + +/* XXX: Stubbed for now */ +void +util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_ia44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ia44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ia44_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ia44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ia44_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} +void +util_format_ai44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ai44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ai44_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ai44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) {} +void +util_format_ai44_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) {} diff --git a/src/gallium/auxiliary/util/u_format_yuv.h b/src/gallium/auxiliary/util/u_format_yuv.h index dc9632346d1..9f2365a5266 100644 --- a/src/gallium/auxiliary/util/u_format_yuv.h +++ b/src/gallium/auxiliary/util/u_format_yuv.h @@ -169,6 +169,141 @@ void util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); +/* XXX: Stubbed for now */ +void +util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_ia44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ia44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ia44_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ia44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ia44_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); +void +util_format_ai44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ai44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ai44_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ai44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); +void +util_format_ai44_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + void util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, diff --git a/src/gallium/auxiliary/util/u_video.h b/src/gallium/auxiliary/util/u_video.h new file mode 100644 index 00000000000..78cceb6bcf2 --- /dev/null +++ b/src/gallium/auxiliary/util/u_video.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_VIDEO_H +#define U_VIDEO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <pipe/p_defines.h> + +/* u_reduce_video_profile() needs these */ +#include <pipe/p_compiler.h> +#include <util/u_debug.h> + +static INLINE enum pipe_video_codec +u_reduce_video_profile(enum pipe_video_profile profile) +{ + switch (profile) + { + case PIPE_VIDEO_PROFILE_MPEG1: + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + return PIPE_VIDEO_CODEC_MPEG12; + + case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: + return PIPE_VIDEO_CODEC_MPEG4; + + case PIPE_VIDEO_PROFILE_VC1_SIMPLE: + case PIPE_VIDEO_PROFILE_VC1_MAIN: + case PIPE_VIDEO_PROFILE_VC1_ADVANCED: + return PIPE_VIDEO_CODEC_VC1; + + case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: + return PIPE_VIDEO_CODEC_MPEG4_AVC; + + default: + assert(0); + return PIPE_VIDEO_CODEC_UNKNOWN; + } +} + +#endif /* U_VIDEO_H */ diff --git a/src/gallium/auxiliary/vl/vl_bitstream_parser.c b/src/gallium/auxiliary/vl/vl_bitstream_parser.c new file mode 100644 index 00000000000..f07b3443b92 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_bitstream_parser.c @@ -0,0 +1,208 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl_bitstream_parser.h" +#include <assert.h> +#include <limits.h> +#include <util/u_memory.h> +#include <stdio.h> + +inline void endian_swap_ushort(unsigned short *x) +{ + x[0] = (x[0]>>8) | + (x[0]<<8); +} + +inline void endian_swap_uint(unsigned int *x) +{ + x[0] = (x[0]>>24) | + ((x[0]<<8) & 0x00FF0000) | + ((x[0]>>8) & 0x0000FF00) | + (x[0]<<24); +} + +inline void endian_swap_ulonglong(unsigned long long *x) +{ + x[0] = (x[0]>>56) | + ((x[0]<<40) & 0x00FF000000000000) | + ((x[0]<<24) & 0x0000FF0000000000) | + ((x[0]<<8) & 0x000000FF00000000) | + ((x[0]>>8) & 0x00000000FF000000) | + ((x[0]>>24) & 0x0000000000FF0000) | + ((x[0]>>40) & 0x000000000000FF00) | + (x[0]<<56); +} + +static unsigned +grab_bits(unsigned cursor, unsigned how_many_bits, unsigned bitstream_elt) +{ + unsigned excess_bits = sizeof(unsigned) * CHAR_BIT - how_many_bits; + + assert(cursor < sizeof(unsigned) * CHAR_BIT); + assert(how_many_bits > 0 && how_many_bits <= sizeof(unsigned) * CHAR_BIT); + assert(cursor + how_many_bits <= sizeof(unsigned) * CHAR_BIT); + + #ifndef PIPE_ARCH_BIG_ENDIAN + switch (sizeof(unsigned)) { + case 2: + endian_swap_ushort(&bitstream_elt); + break; + case 4: + endian_swap_uint(&bitstream_elt); + break; + case 8: + endian_swap_ulonglong(&bitstream_elt); + break; + } + #endif // !PIPE_ARCH_BIG_ENDIAN + + return (bitstream_elt << cursor) >> (excess_bits); +} + +static unsigned +show_bits(unsigned cursor, unsigned how_many_bits, const unsigned *bitstream) +{ + unsigned cur_int = cursor / (sizeof(unsigned) * CHAR_BIT); + unsigned cur_bit = cursor % (sizeof(unsigned) * CHAR_BIT); + + assert(bitstream); + + if (cur_bit + how_many_bits > sizeof(unsigned) * CHAR_BIT) { + unsigned lower = grab_bits(cur_bit, sizeof(unsigned) * CHAR_BIT - cur_bit, + bitstream[cur_int]); + unsigned upper = grab_bits(0, cur_bit + how_many_bits - sizeof(unsigned) * CHAR_BIT, + bitstream[cur_int + 1]); + return lower | upper << (sizeof(unsigned) * CHAR_BIT - cur_bit); + } + else + return grab_bits(cur_bit, how_many_bits, bitstream[cur_int]); +} + +bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser, + unsigned num_bitstreams, + const void **bitstreams, + const unsigned *sizes) +{ + assert(parser); + assert(num_bitstreams); + assert(bitstreams); + assert(sizes); + + parser->num_bitstreams = num_bitstreams; + parser->bitstreams = (const unsigned**)bitstreams; + parser->sizes = sizes; + parser->cur_bitstream = 0; + parser->cursor = 0; + + return true; +} + +void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser) +{ + assert(parser); +} + +unsigned +vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser, + unsigned how_many_bits) +{ + unsigned bits; + + assert(parser); + + bits = vl_bitstream_parser_show_bits(parser, how_many_bits); + + vl_bitstream_parser_forward(parser, how_many_bits); + + return bits; +} + +unsigned +vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser, + unsigned how_many_bits) +{ + unsigned bits = 0; + unsigned shift = 0; + unsigned cursor; + unsigned cur_bitstream; + + assert(parser); + + cursor = parser->cursor; + cur_bitstream = parser->cur_bitstream; + + while (1) { + unsigned bits_left = parser->sizes[cur_bitstream] * CHAR_BIT - cursor; + unsigned bits_to_show = how_many_bits > bits_left ? bits_left : how_many_bits; + + bits |= show_bits(cursor, bits_to_show, + parser->bitstreams[cur_bitstream]) << shift; + + if (how_many_bits > bits_to_show) { + how_many_bits -= bits_to_show; + cursor = 0; + ++cur_bitstream; + shift += bits_to_show; + } + else + break; + } + + return bits; +} + +void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser, + unsigned how_many_bits) +{ + assert(parser); + assert(how_many_bits); + + parser->cursor += how_many_bits; + + while (parser->cursor > parser->sizes[parser->cur_bitstream] * CHAR_BIT) { + parser->cursor -= parser->sizes[parser->cur_bitstream++] * CHAR_BIT; + assert(parser->cur_bitstream < parser->num_bitstreams); + } +} + +void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser, + unsigned how_many_bits) +{ + signed c; + + assert(parser); + assert(how_many_bits); + + c = parser->cursor - how_many_bits; + + while (c < 0) { + c += parser->sizes[parser->cur_bitstream--] * CHAR_BIT; + assert(parser->cur_bitstream < parser->num_bitstreams); + } + + parser->cursor = (unsigned)c; +} diff --git a/src/gallium/auxiliary/vl/vl_bitstream_parser.h b/src/gallium/auxiliary/vl/vl_bitstream_parser.h new file mode 100644 index 00000000000..eeb51dd4295 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_bitstream_parser.h @@ -0,0 +1,67 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_bitstream_parser_h +#define vl_bitstream_parser_h + +#include "pipe/p_compiler.h" + +struct vl_bitstream_parser +{ + unsigned num_bitstreams; + const unsigned **bitstreams; + const unsigned *sizes; + unsigned cur_bitstream; + unsigned cursor; +}; + +inline void endian_swap_ushort(unsigned short *x); +inline void endian_swap_uint(unsigned int *x); +inline void endian_swap_ulonglong(unsigned long long *x); + +bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser, + unsigned num_bitstreams, + const void **bitstreams, + const unsigned *sizes); + +void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser); + +unsigned +vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser, + unsigned how_many_bits); + +unsigned +vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser, + unsigned how_many_bits); + +void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser, + unsigned how_many_bits); + +void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser, + unsigned how_many_bits); + +#endif /* vl_bitstream_parser_h */ diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c new file mode 100644 index 00000000000..d7b29497ace --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -0,0 +1,639 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl_compositor.h" +#include "util/u_draw.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include <util/u_keymap.h> +#include <util/u_draw.h> +#include <util/u_sampler.h> +#include <tgsi/tgsi_ureg.h> +#include "vl_csc.h" + +struct vertex_shader_consts +{ + struct vertex4f dst_scale; + struct vertex4f dst_trans; + struct vertex4f src_scale; + struct vertex4f src_trans; +}; + +struct fragment_shader_consts +{ + float matrix[16]; +}; + +static bool +u_video_rects_equal(struct pipe_video_rect *a, struct pipe_video_rect *b) +{ + assert(a && b); + + if (a->x != b->x) + return false; + if (a->y != b->y) + return false; + if (a->w != b->w) + return false; + if (a->h != b->h) + return false; + + return true; +} + +static bool +create_vert_shader(struct vl_compositor *c) +{ + struct ureg_program *shader; + struct ureg_src vpos, vtex; + struct ureg_dst o_vpos, o_vtex; + + shader = ureg_create(TGSI_PROCESSOR_VERTEX); + if (!shader) + return false; + + vpos = ureg_DECL_vs_input(shader, 0); + vtex = ureg_DECL_vs_input(shader, 1); + o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0); + o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, 1); + + /* + * o_vpos = vpos + * o_vtex = vtex + */ + ureg_MOV(shader, o_vpos, vpos); + ureg_MOV(shader, o_vtex, vtex); + + ureg_END(shader); + + c->vertex_shader = ureg_create_shader_and_destroy(shader, c->pipe); + if (!c->vertex_shader) + return false; + + return true; +} + +static bool +create_frag_shader_ycbcr_2_rgb(struct vl_compositor *c) +{ + struct ureg_program *shader; + struct ureg_src tc; + struct ureg_src csc[4]; + struct ureg_src sampler; + struct ureg_dst texel; + struct ureg_dst fragment; + unsigned i; + + shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!shader) + return false; + + tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR); + for (i = 0; i < 4; ++i) + csc[i] = ureg_DECL_constant(shader, i); + sampler = ureg_DECL_sampler(shader, 0); + texel = ureg_DECL_temporary(shader); + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + /* + * texel = tex(tc, sampler) + * fragment = csc * texel + */ + ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); + for (i = 0; i < 4; ++i) + ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); + + ureg_release_temporary(shader, texel); + ureg_END(shader); + + c->fragment_shader.ycbcr_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe); + if (!c->fragment_shader.ycbcr_2_rgb) + return false; + + return true; +} + +static bool +create_frag_shader_rgb_2_rgb(struct vl_compositor *c) +{ + struct ureg_program *shader; + struct ureg_src tc; + struct ureg_src sampler; + struct ureg_dst fragment; + + shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!shader) + return false; + + tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR); + sampler = ureg_DECL_sampler(shader, 0); + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + /* + * fragment = tex(tc, sampler) + */ + ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler); + ureg_END(shader); + + c->fragment_shader.rgb_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe); + if (!c->fragment_shader.rgb_2_rgb) + return false; + + return true; +} + +static bool +init_pipe_state(struct vl_compositor *c) +{ + struct pipe_sampler_state sampler; + + assert(c); + + c->fb_state.nr_cbufs = 1; + c->fb_state.zsbuf = NULL; + + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + /*sampler.lod_bias = ;*/ + /*sampler.min_lod = ;*/ + /*sampler.max_lod = ;*/ + /*sampler.border_color[i] = ;*/ + /*sampler.max_anisotropy = ;*/ + c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler); + + return true; +} + +static void cleanup_pipe_state(struct vl_compositor *c) +{ + assert(c); + + c->pipe->delete_sampler_state(c->pipe, c->sampler); +} + +static bool +init_shaders(struct vl_compositor *c) +{ + assert(c); + + if (!create_vert_shader(c)) { + debug_printf("Unable to create vertex shader.\n"); + return false; + } + if (!create_frag_shader_ycbcr_2_rgb(c)) { + debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n"); + return false; + } + if (!create_frag_shader_rgb_2_rgb(c)) { + debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); + return false; + } + + return true; +} + +static void cleanup_shaders(struct vl_compositor *c) +{ + assert(c); + + c->pipe->delete_vs_state(c->pipe, c->vertex_shader); + c->pipe->delete_fs_state(c->pipe, c->fragment_shader.ycbcr_2_rgb); + c->pipe->delete_fs_state(c->pipe, c->fragment_shader.rgb_2_rgb); +} + +static bool +init_buffers(struct vl_compositor *c) +{ + struct fragment_shader_consts fsc; + struct pipe_vertex_element vertex_elems[2]; + + assert(c); + + /* + * Create our vertex buffer and vertex buffer elements + */ + c->vertex_buf.stride = sizeof(struct vertex4f); + c->vertex_buf.max_index = (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 - 1; + c->vertex_buf.buffer_offset = 0; + /* XXX: Create with DYNAMIC or STREAM */ + c->vertex_buf.buffer = pipe_buffer_create + ( + c->pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 + ); + + vertex_elems[0].src_offset = 0; + vertex_elems[0].instance_divisor = 0; + vertex_elems[0].vertex_buffer_index = 0; + vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; + vertex_elems[1].src_offset = sizeof(struct vertex2f); + vertex_elems[1].instance_divisor = 0; + vertex_elems[1].vertex_buffer_index = 0; + vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems); + + /* + * Create our fragment shader's constant buffer + * Const buffer contains the color conversion matrix and bias vectors + */ + /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */ + c->fs_const_buf = pipe_buffer_create + ( + c->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, + sizeof(struct fragment_shader_consts) + ); + + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix); + + vl_compositor_set_csc_matrix(c, fsc.matrix); + + return true; +} + +static void +cleanup_buffers(struct vl_compositor *c) +{ + assert(c); + + c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state); + pipe_resource_reference(&c->vertex_buf.buffer, NULL); + pipe_resource_reference(&c->fs_const_buf, NULL); +} + +static void +texview_map_delete(const struct keymap *map, + const void *key, void *data, + void *user) +{ + struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data; + + assert(map); + assert(key); + assert(data); + assert(user); + + pipe_sampler_view_reference(&sv, NULL); +} + +bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe) +{ + unsigned i; + + assert(compositor); + + memset(compositor, 0, sizeof(struct vl_compositor)); + + compositor->pipe = pipe; + + compositor->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1, + texview_map_delete); + if (!compositor->texview_map) + return false; + + if (!init_pipe_state(compositor)) { + util_delete_keymap(compositor->texview_map, compositor->pipe); + return false; + } + if (!init_shaders(compositor)) { + util_delete_keymap(compositor->texview_map, compositor->pipe); + cleanup_pipe_state(compositor); + return false; + } + if (!init_buffers(compositor)) { + util_delete_keymap(compositor->texview_map, compositor->pipe); + cleanup_shaders(compositor); + cleanup_pipe_state(compositor); + return false; + } + + compositor->fb_state.width = 0; + compositor->fb_state.height = 0; + compositor->bg = NULL; + compositor->dirty_bg = false; + for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) + compositor->layers[i] = NULL; + compositor->dirty_layers = 0; + + return true; +} + +void vl_compositor_cleanup(struct vl_compositor *compositor) +{ + assert(compositor); + + util_delete_keymap(compositor->texview_map, compositor->pipe); + cleanup_buffers(compositor); + cleanup_shaders(compositor); + cleanup_pipe_state(compositor); +} + +void vl_compositor_set_background(struct vl_compositor *compositor, + struct pipe_surface *bg, struct pipe_video_rect *bg_src_rect) +{ + assert(compositor); + assert((bg && bg_src_rect) || (!bg && !bg_src_rect)); + + if (compositor->bg != bg || + !u_video_rects_equal(&compositor->bg_src_rect, bg_src_rect)) { + pipe_surface_reference(&compositor->bg, bg); + /*if (!u_video_rects_equal(&compositor->bg_src_rect, bg_src_rect))*/ + compositor->bg_src_rect = *bg_src_rect; + compositor->dirty_bg = true; + } +} + +void vl_compositor_set_layers(struct vl_compositor *compositor, + struct pipe_surface *layers[], + struct pipe_video_rect *src_rects[], + struct pipe_video_rect *dst_rects[], + unsigned num_layers) +{ + unsigned i; + + assert(compositor); + assert(num_layers <= VL_COMPOSITOR_MAX_LAYERS); + + for (i = 0; i < num_layers; ++i) + { + assert((layers[i] && src_rects[i] && dst_rects[i]) || + (!layers[i] && !src_rects[i] && !dst_rects[i])); + + if (compositor->layers[i] != layers[i] || + !u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]) || + !u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i])) + { + pipe_surface_reference(&compositor->layers[i], layers[i]); + /*if (!u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]))*/ + compositor->layer_src_rects[i] = *src_rects[i]; + /*if (!u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i]))*/ + compositor->layer_dst_rects[i] = *dst_rects[i]; + compositor->dirty_layers |= 1 << i; + } + + if (layers[i]) + compositor->dirty_layers |= 1 << i; + } + + for (; i < VL_COMPOSITOR_MAX_LAYERS; ++i) + pipe_surface_reference(&compositor->layers[i], NULL); +} + +static void gen_rect_verts(unsigned pos, + struct pipe_video_rect *src_rect, + struct vertex2f *src_inv_size, + struct pipe_video_rect *dst_rect, + struct vertex2f *dst_inv_size, + struct vertex4f *vb) +{ + assert(pos < VL_COMPOSITOR_MAX_LAYERS + 2); + assert(src_rect); + assert(src_inv_size); + assert((dst_rect && dst_inv_size) /*|| (!dst_rect && !dst_inv_size)*/); + assert(vb); + + vb[pos * 6 + 0].x = dst_rect->x * dst_inv_size->x; + vb[pos * 6 + 0].y = dst_rect->y * dst_inv_size->y; + vb[pos * 6 + 0].z = src_rect->x * src_inv_size->x; + vb[pos * 6 + 0].w = src_rect->y * src_inv_size->y; + + vb[pos * 6 + 1].x = dst_rect->x * dst_inv_size->x; + vb[pos * 6 + 1].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y; + vb[pos * 6 + 1].z = src_rect->x * src_inv_size->x; + vb[pos * 6 + 1].w = (src_rect->y + src_rect->h) * src_inv_size->y; + + vb[pos * 6 + 2].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x; + vb[pos * 6 + 2].y = dst_rect->y * dst_inv_size->y; + vb[pos * 6 + 2].z = (src_rect->x + src_rect->w) * src_inv_size->x; + vb[pos * 6 + 2].w = src_rect->y * src_inv_size->y; + + vb[pos * 6 + 3].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x; + vb[pos * 6 + 3].y = dst_rect->y * dst_inv_size->y; + vb[pos * 6 + 3].z = (src_rect->x + src_rect->w) * src_inv_size->x; + vb[pos * 6 + 3].w = src_rect->y * src_inv_size->y; + + vb[pos * 6 + 4].x = dst_rect->x * dst_inv_size->x; + vb[pos * 6 + 4].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y; + vb[pos * 6 + 4].z = src_rect->x * src_inv_size->x; + vb[pos * 6 + 4].w = (src_rect->y + src_rect->h) * src_inv_size->y; + + vb[pos * 6 + 5].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x; + vb[pos * 6 + 5].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y; + vb[pos * 6 + 5].z = (src_rect->x + src_rect->w) * src_inv_size->x; + vb[pos * 6 + 5].w = (src_rect->y + src_rect->h) * src_inv_size->y; +} + +static unsigned gen_data(struct vl_compositor *c, + struct pipe_surface *src_surface, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect, + struct pipe_surface **textures, + void **frag_shaders) +{ + void *vb; + struct pipe_transfer *buf_transfer; + unsigned num_rects = 0; + unsigned i; + + assert(c); + assert(src_surface); + assert(src_rect); + assert(dst_rect); + assert(textures); + + vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &buf_transfer); + + if (!vb) + return 0; + + if (c->dirty_bg) { + struct vertex2f bg_inv_size = {1.0f / c->bg->width, 1.0f / c->bg->height}; + gen_rect_verts(num_rects, &c->bg_src_rect, &bg_inv_size, NULL, NULL, vb); + textures[num_rects] = c->bg; + /* XXX: Hack */ + frag_shaders[num_rects] = c->fragment_shader.rgb_2_rgb; + ++num_rects; + c->dirty_bg = false; + } + + { + struct vertex2f src_inv_size = { 1.0f / src_surface->width, 1.0f / src_surface->height}; + gen_rect_verts(num_rects, src_rect, &src_inv_size, dst_rect, &c->fb_inv_size, vb); + textures[num_rects] = src_surface; + /* XXX: Hack, sort of */ + frag_shaders[num_rects] = c->fragment_shader.ycbcr_2_rgb; + ++num_rects; + } + + for (i = 0; c->dirty_layers > 0; i++) { + assert(i < VL_COMPOSITOR_MAX_LAYERS); + + if (c->dirty_layers & (1 << i)) { + struct vertex2f layer_inv_size = {1.0f / c->layers[i]->width, 1.0f / c->layers[i]->height}; + gen_rect_verts(num_rects, &c->layer_src_rects[i], &layer_inv_size, + &c->layer_dst_rects[i], &c->fb_inv_size, vb); + textures[num_rects] = c->layers[i]; + /* XXX: Hack */ + frag_shaders[num_rects] = c->fragment_shader.rgb_2_rgb; + ++num_rects; + c->dirty_layers &= ~(1 << i); + } + } + + pipe_buffer_unmap(c->pipe, buf_transfer); + + return num_rects; +} + +static void draw_layers(struct vl_compositor *c, + struct pipe_surface *src_surface, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect) +{ + unsigned num_rects; + struct pipe_surface *src_surfaces[VL_COMPOSITOR_MAX_LAYERS + 2]; + void *frag_shaders[VL_COMPOSITOR_MAX_LAYERS + 2]; + unsigned i; + + assert(c); + assert(src_surface); + assert(src_rect); + assert(dst_rect); + + num_rects = gen_data(c, src_surface, src_rect, dst_rect, src_surfaces, frag_shaders); + + for (i = 0; i < num_rects; ++i) { + boolean delete_view = FALSE; + struct pipe_sampler_view *surface_view = (struct pipe_sampler_view*)util_keymap_lookup(c->texview_map, + &src_surfaces[i]); + if (!surface_view) { + struct pipe_sampler_view templat; + u_sampler_view_default_template(&templat, src_surfaces[i]->texture, + src_surfaces[i]->texture->format); + surface_view = c->pipe->create_sampler_view(c->pipe, src_surfaces[i]->texture, + &templat); + if (!surface_view) + return; + + delete_view = !util_keymap_insert(c->texview_map, &src_surfaces[i], + surface_view, c->pipe); + } + + c->pipe->bind_fs_state(c->pipe, frag_shaders[i]); + c->pipe->set_fragment_sampler_views(c->pipe, 1, &surface_view); + + util_draw_arrays(c->pipe, PIPE_PRIM_TRIANGLES, i * 6, 6); + + if (delete_view) { + pipe_sampler_view_reference(&surface_view, NULL); + } + } +} + +void vl_compositor_render(struct vl_compositor *compositor, + struct pipe_surface *src_surface, + enum pipe_mpeg12_picture_type picture_type, + /*unsigned num_past_surfaces, + struct pipe_surface *past_surfaces, + unsigned num_future_surfaces, + struct pipe_surface *future_surfaces,*/ + struct pipe_video_rect *src_area, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence) +{ + assert(compositor); + assert(src_surface); + assert(src_area); + assert(dst_surface); + assert(dst_area); + assert(picture_type == PIPE_MPEG12_PICTURE_TYPE_FRAME); + + if (compositor->fb_state.width != dst_surface->width) { + compositor->fb_inv_size.x = 1.0f / dst_surface->width; + compositor->fb_state.width = dst_surface->width; + } + if (compositor->fb_state.height != dst_surface->height) { + compositor->fb_inv_size.y = 1.0f / dst_surface->height; + compositor->fb_state.height = dst_surface->height; + } + + compositor->fb_state.cbufs[0] = dst_surface; + + compositor->viewport.scale[0] = compositor->fb_state.width; + compositor->viewport.scale[1] = compositor->fb_state.height; + compositor->viewport.scale[2] = 1; + compositor->viewport.scale[3] = 1; + compositor->viewport.translate[0] = 0; + compositor->viewport.translate[1] = 0; + compositor->viewport.translate[2] = 0; + compositor->viewport.translate[3] = 0; + + compositor->pipe->set_framebuffer_state(compositor->pipe, &compositor->fb_state); + compositor->pipe->set_viewport_state(compositor->pipe, &compositor->viewport); + compositor->pipe->bind_fragment_sampler_states(compositor->pipe, 1, &compositor->sampler); + compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader); + compositor->pipe->set_vertex_buffers(compositor->pipe, 1, &compositor->vertex_buf); + compositor->pipe->bind_vertex_elements_state(compositor->pipe, compositor->vertex_elems_state); + compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, compositor->fs_const_buf); + + draw_layers(compositor, src_surface, src_area, dst_area); + + assert(!compositor->dirty_bg && !compositor->dirty_layers); + compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence); +} + +void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat) +{ + struct pipe_transfer *buf_transfer; + + assert(compositor); + + memcpy + ( + pipe_buffer_map(compositor->pipe, compositor->fs_const_buf, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &buf_transfer), + mat, + sizeof(struct fragment_shader_consts) + ); + + pipe_buffer_unmap(compositor->pipe, buf_transfer); +} diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h new file mode 100644 index 00000000000..820c9ef6ddb --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_compositor.h @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_compositor_h +#define vl_compositor_h + +#include <pipe/p_compiler.h> +#include <pipe/p_state.h> +#include <pipe/p_video_state.h> +#include "vl_types.h" + +struct pipe_context; +struct keymap; + +#define VL_COMPOSITOR_MAX_LAYERS 16 + +struct vl_compositor +{ + struct pipe_context *pipe; + + struct pipe_framebuffer_state fb_state; + struct vertex2f fb_inv_size; + void *sampler; + struct pipe_sampler_view *sampler_view; + void *vertex_shader; + struct + { + void *ycbcr_2_rgb; + void *rgb_2_rgb; + } fragment_shader; + struct pipe_viewport_state viewport; + struct pipe_vertex_buffer vertex_buf; + void *vertex_elems_state; + struct pipe_resource *fs_const_buf; + + struct pipe_surface *bg; + struct pipe_video_rect bg_src_rect; + bool dirty_bg; + struct pipe_surface *layers[VL_COMPOSITOR_MAX_LAYERS]; + struct pipe_video_rect layer_src_rects[VL_COMPOSITOR_MAX_LAYERS]; + struct pipe_video_rect layer_dst_rects[VL_COMPOSITOR_MAX_LAYERS]; + unsigned dirty_layers; + + struct keymap *texview_map; +}; + +bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe); + +void vl_compositor_cleanup(struct vl_compositor *compositor); + +void vl_compositor_set_background(struct vl_compositor *compositor, + struct pipe_surface *bg, struct pipe_video_rect *bg_src_rect); + +void vl_compositor_set_layers(struct vl_compositor *compositor, + struct pipe_surface *layers[], + struct pipe_video_rect *src_rects[], + struct pipe_video_rect *dst_rects[], + unsigned num_layers); + +void vl_compositor_render(struct vl_compositor *compositor, + struct pipe_surface *src_surface, + enum pipe_mpeg12_picture_type picture_type, + /*unsigned num_past_surfaces, + struct pipe_surface *past_surfaces, + unsigned num_future_surfaces, + struct pipe_surface *future_surfaces,*/ + struct pipe_video_rect *src_area, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence); + +void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat); + +#endif /* vl_compositor_h */ diff --git a/src/gallium/auxiliary/vl/vl_csc.c b/src/gallium/auxiliary/vl/vl_csc.c new file mode 100644 index 00000000000..5ecc43a5fa3 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_csc.c @@ -0,0 +1,206 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl_csc.h" +#include <util/u_math.h> +#include <util/u_debug.h> + +/* + * Color space conversion formulas + * + * To convert YCbCr to RGB, + * vec4 ycbcr, rgb + * mat44 csc + * rgb = csc * ycbcr + * + * To calculate the color space conversion matrix csc with ProcAmp adjustments, + * mat44 csc, cstd, procamp, bias + * csc = cstd * (procamp * bias) + * + * Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc) + * adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full), + * bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full) + * + * To calculate procamp, + * mat44 procamp, hue, saturation, brightness, contrast + * procamp = brightness * (saturation * (contrast * hue)) + * Alternatively, + * procamp = saturation * (brightness * (contrast * hue)) + * + * contrast + * [ c, 0, 0, 0] + * [ 0, c, 0, 0] + * [ 0, 0, c, 0] + * [ 0, 0, 0, 1] + * + * brightness + * [ 1, 0, 0, b] + * [ 0, 1, 0, 0] + * [ 0, 0, 1, 0] + * [ 0, 0, 0, 1] + * + * saturation + * [ 1, 0, 0, 0] + * [ 0, s, 0, 0] + * [ 0, 0, s, 0] + * [ 0, 0, 0, 1] + * + * hue + * [ 1, 0, 0, 0] + * [ 0, cos(h), sin(h), 0] + * [ 0, -sin(h), cos(h), 0] + * [ 0, 0, 0, 1] + * + * procamp + * [ c, 0, 0, b] + * [ 0, c*s*cos(h), c*s*sin(h), 0] + * [ 0, -c*s*sin(h), c*s*cos(h), 0] + * [ 0, 0, 0, 1] + * + * bias + * [ 1, 0, 0, ybias] + * [ 0, 1, 0, cbbias] + * [ 0, 0, 1, crbias] + * [ 0, 0, 0, 1] + * + * csc + * [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + * [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] + */ + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const float bt_601[16] = +{ + 1.0f, 0.0f, 1.371f, 0.0f, + 1.0f, -0.336f, -0.698f, 0.0f, + 1.0f, 1.732f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +static const float bt_601_full[16] = +{ + 1.164f, 0.0f, 1.596f, 0.0f, + 1.164f, -0.391f, -0.813f, 0.0f, + 1.164f, 2.018f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const float bt_709[16] = +{ + 1.0f, 0.0f, 1.540f, 0.0f, + 1.0f, -0.183f, -0.459f, 0.0f, + 1.0f, 1.816f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +static const float bt_709_full[16] = +{ + 1.164f, 0.0f, 1.793f, 0.0f, + 1.164f, -0.213f, -0.534f, 0.0f, + 1.164f, 2.115f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f +}; + +static const float identity[16] = +{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f +}; + +void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, + struct vl_procamp *procamp, + bool full_range, + float *matrix) +{ + float ybias = full_range ? -16.0f/255.0f : 0.0f; + float cbbias = -128.0f/255.0f; + float crbias = -128.0f/255.0f; + float c = procamp ? procamp->contrast : 1.0f; + float s = procamp ? procamp->saturation : 1.0f; + float b = procamp ? procamp->brightness : 0.0f; + float h = procamp ? procamp->hue : 0.0f; + const float *cstd; + + assert(matrix); + + switch (cs) { + case VL_CSC_COLOR_STANDARD_BT_601: + cstd = full_range ? &bt_601_full[0] : &bt_601[0]; + break; + case VL_CSC_COLOR_STANDARD_BT_709: + cstd = full_range ? &bt_709_full[0] : &bt_709[0]; + break; + case VL_CSC_COLOR_STANDARD_IDENTITY: + default: + assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY); + memcpy(matrix, &identity[0], sizeof(float) * 16); + return; + } + + matrix[ 0] = c*cstd[ 0]; + matrix[ 1] = c*cstd[ 1]*s*cosf(h) - c*cstd[ 2]*s*sinf(h); + matrix[ 2] = c*cstd[ 2]*s*cosf(h) + c*cstd[ 1]*s*sinf(h); + matrix[ 3] = cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 2]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + + matrix[ 4] = c*cstd[ 4]; + matrix[ 5] = c*cstd[ 5]*s*cosf(h) - c*cstd[ 6]*s*sinf(h); + matrix[ 6] = c*cstd[ 6]*s*cosf(h) + c*cstd[ 5]*s*sinf(h); + matrix[ 7] = cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 6]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + + matrix[ 8] = c*cstd[ 8]; + matrix[ 9] = c*cstd[ 9]*s*cosf(h) - c*cstd[10]*s*sinf(h); + matrix[10] = c*cstd[10]*s*cosf(h) + c*cstd[ 9]*s*sinf(h); + matrix[11] = cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[10]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h)); + + matrix[12] = c*cstd[12]; + matrix[13] = c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h); + matrix[14] = c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h); + matrix[15] = cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h)); +} diff --git a/src/gallium/auxiliary/vl/vl_csc.h b/src/gallium/auxiliary/vl/vl_csc.h new file mode 100644 index 00000000000..722ca35f339 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_csc.h @@ -0,0 +1,53 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_csc_h +#define vl_csc_h + +#include <pipe/p_compiler.h> + +struct vl_procamp +{ + float brightness; + float contrast; + float saturation; + float hue; +}; + +enum VL_CSC_COLOR_STANDARD +{ + VL_CSC_COLOR_STANDARD_IDENTITY, + VL_CSC_COLOR_STANDARD_BT_601, + VL_CSC_COLOR_STANDARD_BT_709 +}; + +void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, + struct vl_procamp *procamp, + bool full_range, + float *matrix); + +#endif /* vl_csc_h */ diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c new file mode 100644 index 00000000000..5d472f93481 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_idct.c @@ -0,0 +1,766 @@ +/************************************************************************** + * + * Copyright 2010 Christian König + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl_idct.h" +#include "vl_vertex_buffers.h" +#include "util/u_draw.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <util/u_inlines.h> +#include <util/u_sampler.h> +#include <util/u_format.h> +#include <tgsi/tgsi_ureg.h> +#include "vl_types.h" + +#define BLOCK_WIDTH 8 +#define BLOCK_HEIGHT 8 + +#define SCALE_FACTOR_16_TO_9 (32768.0f / 256.0f) + +#define NR_RENDER_TARGETS 4 + +enum VS_INPUT +{ + VS_I_RECT, + VS_I_VPOS, + + NUM_VS_INPUTS +}; + +enum VS_OUTPUT +{ + VS_O_VPOS, + VS_O_L_ADDR0, + VS_O_L_ADDR1, + VS_O_R_ADDR0, + VS_O_R_ADDR1 +}; + +static const float const_matrix[8][8] = { + { 0.3535530f, 0.3535530f, 0.3535530f, 0.3535530f, 0.3535530f, 0.3535530f, 0.353553f, 0.3535530f }, + { 0.4903930f, 0.4157350f, 0.2777850f, 0.0975451f, -0.0975452f, -0.2777850f, -0.415735f, -0.4903930f }, + { 0.4619400f, 0.1913420f, -0.1913420f, -0.4619400f, -0.4619400f, -0.1913420f, 0.191342f, 0.4619400f }, + { 0.4157350f, -0.0975452f, -0.4903930f, -0.2777850f, 0.2777850f, 0.4903930f, 0.097545f, -0.4157350f }, + { 0.3535530f, -0.3535530f, -0.3535530f, 0.3535540f, 0.3535530f, -0.3535540f, -0.353553f, 0.3535530f }, + { 0.2777850f, -0.4903930f, 0.0975452f, 0.4157350f, -0.4157350f, -0.0975451f, 0.490393f, -0.2777850f }, + { 0.1913420f, -0.4619400f, 0.4619400f, -0.1913420f, -0.1913410f, 0.4619400f, -0.461940f, 0.1913420f }, + { 0.0975451f, -0.2777850f, 0.4157350f, -0.4903930f, 0.4903930f, -0.4157350f, 0.277786f, -0.0975458f } +}; + +static void +calc_addr(struct ureg_program *shader, struct ureg_dst addr[2], + struct ureg_src tc, struct ureg_src start, bool right_side, + bool transposed, float size) +{ + unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y; + unsigned sw_start = right_side ? TGSI_SWIZZLE_Y : TGSI_SWIZZLE_X; + + unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X; + unsigned sw_tc = right_side ? TGSI_SWIZZLE_X : TGSI_SWIZZLE_Y; + + /* + * addr[0..1].(start) = right_side ? start.x : tc.x + * addr[0..1].(tc) = right_side ? tc.y : start.y + * addr[0..1].z = tc.z + * addr[1].(start) += 1.0f / scale + */ + ureg_MOV(shader, ureg_writemask(addr[0], wm_start), ureg_scalar(start, sw_start)); + ureg_MOV(shader, ureg_writemask(addr[0], wm_tc), ureg_scalar(tc, sw_tc)); + ureg_MOV(shader, ureg_writemask(addr[0], TGSI_WRITEMASK_Z), tc); + + ureg_ADD(shader, ureg_writemask(addr[1], wm_start), ureg_scalar(start, sw_start), ureg_imm1f(shader, 1.0f / size)); + ureg_MOV(shader, ureg_writemask(addr[1], wm_tc), ureg_scalar(tc, sw_tc)); + ureg_MOV(shader, ureg_writemask(addr[1], TGSI_WRITEMASK_Z), tc); +} + +static void * +create_vert_shader(struct vl_idct *idct, bool matrix_stage) +{ + struct ureg_program *shader; + struct ureg_src scale; + struct ureg_src vrect, vpos; + struct ureg_dst t_tex, t_start; + struct ureg_dst o_vpos, o_l_addr[2], o_r_addr[2]; + + shader = ureg_create(TGSI_PROCESSOR_VERTEX); + if (!shader) + return NULL; + + t_tex = ureg_DECL_temporary(shader); + t_start = ureg_DECL_temporary(shader); + + vrect = ureg_DECL_vs_input(shader, VS_I_RECT); + vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); + + o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); + + o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0); + o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1); + + o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0); + o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1); + + /* + * scale = (BLOCK_WIDTH, BLOCK_HEIGHT) / (dst.width, dst.height) + * + * t_vpos = vpos + vrect + * o_vpos.xy = t_vpos * scale + * o_vpos.zw = vpos + * + * o_l_addr = calc_addr(...) + * o_r_addr = calc_addr(...) + * + */ + scale = ureg_imm2f(shader, + (float)BLOCK_WIDTH / idct->buffer_width, + (float)BLOCK_HEIGHT / idct->buffer_height); + + ureg_ADD(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, vrect); + ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), ureg_src(t_tex), scale); + ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_Z), + ureg_scalar(vrect, TGSI_SWIZZLE_X), + ureg_imm1f(shader, BLOCK_WIDTH / NR_RENDER_TARGETS)); + + ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_tex)); + ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos); + + ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale); + + if(matrix_stage) { + calc_addr(shader, o_l_addr, ureg_src(t_tex), ureg_src(t_start), false, false, idct->buffer_width / 4); + calc_addr(shader, o_r_addr, vrect, ureg_imm1f(shader, 0.0f), true, true, BLOCK_WIDTH / 4); + } else { + calc_addr(shader, o_l_addr, vrect, ureg_imm1f(shader, 0.0f), false, false, BLOCK_WIDTH / 4); + calc_addr(shader, o_r_addr, ureg_src(t_tex), ureg_src(t_start), true, false, idct->buffer_height / 4); + } + + ureg_release_temporary(shader, t_tex); + ureg_release_temporary(shader, t_start); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, idct->pipe); +} + +static void +increment_addr(struct ureg_program *shader, struct ureg_dst daddr[2], + struct ureg_src saddr[2], bool right_side, bool transposed, + int pos, float size) +{ + unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y; + unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X; + + /* + * daddr[0..1].(start) = saddr[0..1].(start) + * daddr[0..1].(tc) = saddr[0..1].(tc) + */ + + ureg_MOV(shader, ureg_writemask(daddr[0], wm_start), saddr[0]); + ureg_ADD(shader, ureg_writemask(daddr[0], wm_tc), saddr[0], ureg_imm1f(shader, pos / size)); + ureg_MOV(shader, ureg_writemask(daddr[1], wm_start), saddr[1]); + ureg_ADD(shader, ureg_writemask(daddr[1], wm_tc), saddr[1], ureg_imm1f(shader, pos / size)); +} + +static void +fetch_four(struct ureg_program *shader, struct ureg_dst m[2], struct ureg_src addr[2], struct ureg_src sampler) +{ + ureg_TEX(shader, m[0], TGSI_TEXTURE_3D, addr[0], sampler); + ureg_TEX(shader, m[1], TGSI_TEXTURE_3D, addr[1], sampler); +} + +static void +matrix_mul(struct ureg_program *shader, struct ureg_dst dst, struct ureg_dst l[2], struct ureg_dst r[2]) +{ + struct ureg_dst tmp; + + tmp = ureg_DECL_temporary(shader); + + /* + * tmp.xy = dot4(m[0][0..1], m[1][0..1]) + * dst = tmp.x + tmp.y + */ + ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(l[0]), ureg_src(r[0])); + ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(l[1]), ureg_src(r[1])); + ureg_ADD(shader, dst, + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); + + ureg_release_temporary(shader, tmp); +} + +static void * +create_matrix_frag_shader(struct vl_idct *idct) +{ + struct ureg_program *shader; + + struct ureg_src l_addr[2], r_addr[2]; + + struct ureg_dst l[4][2], r[2]; + struct ureg_dst fragment[NR_RENDER_TARGETS]; + + unsigned i, j; + + shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!shader) + return NULL; + + l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR); + l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR); + + r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR); + r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR); + + for (i = 0; i < NR_RENDER_TARGETS; ++i) + fragment[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, i); + + for (i = 0; i < 4; ++i) { + l[i][0] = ureg_DECL_temporary(shader); + l[i][1] = ureg_DECL_temporary(shader); + } + + r[0] = ureg_DECL_temporary(shader); + r[1] = ureg_DECL_temporary(shader); + + for (i = 1; i < 4; ++i) { + increment_addr(shader, l[i], l_addr, false, false, i, idct->buffer_height); + } + + for (i = 0; i < 4; ++i) { + struct ureg_src s_addr[2]; + s_addr[0] = i == 0 ? l_addr[0] : ureg_src(l[i][0]); + s_addr[1] = i == 0 ? l_addr[1] : ureg_src(l[i][1]); + fetch_four(shader, l[i], s_addr, ureg_DECL_sampler(shader, 1)); + } + + for (i = 0; i < NR_RENDER_TARGETS; ++i) { + if(i > 0) + increment_addr(shader, r, r_addr, true, true, i, BLOCK_HEIGHT); + + struct ureg_src s_addr[2] = { ureg_src(r[0]), ureg_src(r[1]) }; + s_addr[0] = i == 0 ? r_addr[0] : ureg_src(r[0]); + s_addr[1] = i == 0 ? r_addr[1] : ureg_src(r[1]); + fetch_four(shader, r, s_addr, ureg_DECL_sampler(shader, 0)); + + for (j = 0; j < 4; ++j) { + matrix_mul(shader, ureg_writemask(fragment[i], TGSI_WRITEMASK_X << j), l[j], r); + } + } + + for (i = 0; i < 4; ++i) { + ureg_release_temporary(shader, l[i][0]); + ureg_release_temporary(shader, l[i][1]); + } + ureg_release_temporary(shader, r[0]); + ureg_release_temporary(shader, r[1]); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, idct->pipe); +} + +static void * +create_transpose_frag_shader(struct vl_idct *idct) +{ + struct ureg_program *shader; + + struct ureg_src l_addr[2], r_addr[2]; + + struct ureg_dst l[2], r[2]; + struct ureg_dst fragment; + + shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!shader) + return NULL; + + l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR); + l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR); + + r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR); + r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR); + + l[0] = ureg_DECL_temporary(shader); + l[1] = ureg_DECL_temporary(shader); + r[0] = ureg_DECL_temporary(shader); + r[1] = ureg_DECL_temporary(shader); + + fetch_four(shader, l, l_addr, ureg_DECL_sampler(shader, 0)); + fetch_four(shader, r, r_addr, ureg_DECL_sampler(shader, 1)); + + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + matrix_mul(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X), l, r); + + ureg_release_temporary(shader, l[0]); + ureg_release_temporary(shader, l[1]); + ureg_release_temporary(shader, r[0]); + ureg_release_temporary(shader, r[1]); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, idct->pipe); +} + +static bool +init_shaders(struct vl_idct *idct) +{ + idct->matrix_vs = create_vert_shader(idct, true); + idct->matrix_fs = create_matrix_frag_shader(idct); + + idct->transpose_vs = create_vert_shader(idct, false); + idct->transpose_fs = create_transpose_frag_shader(idct); + + return + idct->matrix_vs != NULL && + idct->matrix_fs != NULL && + idct->transpose_vs != NULL && + idct->transpose_fs != NULL; +} + +static void +cleanup_shaders(struct vl_idct *idct) +{ + idct->pipe->delete_vs_state(idct->pipe, idct->matrix_vs); + idct->pipe->delete_fs_state(idct->pipe, idct->matrix_fs); + idct->pipe->delete_vs_state(idct->pipe, idct->transpose_vs); + idct->pipe->delete_fs_state(idct->pipe, idct->transpose_fs); +} + +static bool +init_state(struct vl_idct *idct) +{ + struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; + struct pipe_sampler_state sampler; + struct pipe_rasterizer_state rs_state; + unsigned i; + + assert(idct); + + idct->quad = vl_vb_upload_quads(idct->pipe, idct->max_blocks); + + if(idct->quad.buffer == NULL) + return false; + + for (i = 0; i < 4; ++i) { + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; + sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; + sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + /*sampler.shadow_ambient = ; */ + /*sampler.lod_bias = ; */ + sampler.min_lod = 0; + /*sampler.max_lod = ; */ + /*sampler.border_color[0] = ; */ + /*sampler.max_anisotropy = ; */ + idct->samplers.all[i] = idct->pipe->create_sampler_state(idct->pipe, &sampler); + } + + memset(&rs_state, 0, sizeof(rs_state)); + /*rs_state.sprite_coord_enable */ + rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; + rs_state.point_quad_rasterization = true; + rs_state.point_size = BLOCK_WIDTH; + rs_state.gl_rasterization_rules = false; + idct->rs_state = idct->pipe->create_rasterizer_state(idct->pipe, &rs_state); + + vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); + + /* Pos element */ + vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; + + idct->vertex_buffer_stride = vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1); + idct->vertex_elems_state = idct->pipe->create_vertex_elements_state(idct->pipe, 2, vertex_elems); + + return true; +} + +static void +cleanup_state(struct vl_idct *idct) +{ + unsigned i; + + for (i = 0; i < 4; ++i) + idct->pipe->delete_sampler_state(idct->pipe, idct->samplers.all[i]); + + idct->pipe->delete_rasterizer_state(idct->pipe, idct->rs_state); + idct->pipe->delete_vertex_elements_state(idct->pipe, idct->vertex_elems_state); +} + +static bool +init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + struct pipe_resource template; + struct pipe_sampler_view sampler_view; + unsigned i; + + assert(idct && buffer); + + /* create textures */ + memset(&template, 0, sizeof(struct pipe_resource)); + template.last_level = 0; + template.depth0 = 1; + template.bind = PIPE_BIND_SAMPLER_VIEW; + template.flags = 0; + + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_R16G16B16A16_SNORM; + template.width0 = idct->buffer_width / 4; + template.height0 = idct->buffer_height; + template.depth0 = 1; + template.usage = PIPE_USAGE_STREAM; + buffer->textures.individual.source = idct->pipe->screen->resource_create(idct->pipe->screen, &template); + + template.target = PIPE_TEXTURE_3D; + template.format = PIPE_FORMAT_R16G16B16A16_SNORM; + template.width0 = idct->buffer_width / NR_RENDER_TARGETS; + template.height0 = idct->buffer_height / 4; + template.depth0 = NR_RENDER_TARGETS; + template.usage = PIPE_USAGE_STATIC; + buffer->textures.individual.intermediate = idct->pipe->screen->resource_create(idct->pipe->screen, &template); + + for (i = 0; i < 4; ++i) { + if(buffer->textures.all[i] == NULL) + return false; /* a texture failed to allocate */ + + u_sampler_view_default_template(&sampler_view, buffer->textures.all[i], buffer->textures.all[i]->format); + buffer->sampler_views.all[i] = idct->pipe->create_sampler_view(idct->pipe, buffer->textures.all[i], &sampler_view); + } + + return true; +} + +static void +cleanup_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + unsigned i; + + assert(idct && buffer); + + for (i = 0; i < 4; ++i) { + pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL); + pipe_resource_reference(&buffer->textures.all[i], NULL); + } +} + +static bool +init_vertex_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + assert(idct && buffer); + + buffer->vertex_bufs.individual.quad.stride = idct->quad.stride; + buffer->vertex_bufs.individual.quad.max_index = idct->quad.max_index; + buffer->vertex_bufs.individual.quad.buffer_offset = idct->quad.buffer_offset; + pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, idct->quad.buffer); + + buffer->vertex_bufs.individual.pos = vl_vb_init( + &buffer->blocks, idct->pipe, idct->max_blocks, + idct->vertex_buffer_stride); + + if(buffer->vertex_bufs.individual.pos.buffer == NULL) + return false; + + return true; +} + +static void +cleanup_vertex_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + assert(idct && buffer); + + pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, NULL); + pipe_resource_reference(&buffer->vertex_bufs.individual.pos.buffer, NULL); + + vl_vb_cleanup(&buffer->blocks); +} + +struct pipe_resource * +vl_idct_upload_matrix(struct pipe_context *pipe) +{ + struct pipe_resource template, *matrix; + struct pipe_transfer *buf_transfer; + unsigned i, j, pitch; + float *f; + + struct pipe_box rect = + { + 0, 0, 0, + BLOCK_WIDTH / 4, + BLOCK_HEIGHT, + 1 + }; + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_R32G32B32A32_FLOAT; + template.last_level = 0; + template.width0 = 2; + template.height0 = 8; + template.depth0 = 1; + template.usage = PIPE_USAGE_IMMUTABLE; + template.bind = PIPE_BIND_SAMPLER_VIEW; + template.flags = 0; + + matrix = pipe->screen->resource_create(pipe->screen, &template); + + /* matrix */ + buf_transfer = pipe->get_transfer + ( + pipe, matrix, + 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &rect + ); + pitch = buf_transfer->stride / sizeof(float); + + f = pipe->transfer_map(pipe, buf_transfer); + for(i = 0; i < BLOCK_HEIGHT; ++i) + for(j = 0; j < BLOCK_WIDTH; ++j) + // transpose and scale + f[i * pitch + j] = const_matrix[j][i] * sqrtf(SCALE_FACTOR_16_TO_9); + + pipe->transfer_unmap(pipe, buf_transfer); + pipe->transfer_destroy(pipe, buf_transfer); + + return matrix; +} + +bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe, + unsigned buffer_width, unsigned buffer_height, + struct pipe_resource *matrix) +{ + assert(idct && pipe && matrix); + + idct->pipe = pipe; + idct->buffer_width = buffer_width; + idct->buffer_height = buffer_height; + pipe_resource_reference(&idct->matrix, matrix); + + idct->max_blocks = + align(buffer_width, BLOCK_WIDTH) / BLOCK_WIDTH * + align(buffer_height, BLOCK_HEIGHT) / BLOCK_HEIGHT; + + if(!init_shaders(idct)) + return false; + + if(!init_state(idct)) { + cleanup_shaders(idct); + return false; + } + + return true; +} + +void +vl_idct_cleanup(struct vl_idct *idct) +{ + cleanup_shaders(idct); + cleanup_state(idct); + + pipe_resource_reference(&idct->matrix, NULL); +} + +bool +vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer, struct pipe_resource *dst) +{ + struct pipe_surface template; + + unsigned i; + + assert(buffer); + assert(idct); + assert(dst); + + pipe_resource_reference(&buffer->textures.individual.matrix, idct->matrix); + pipe_resource_reference(&buffer->textures.individual.transpose, idct->matrix); + pipe_resource_reference(&buffer->destination, dst); + + if (!init_textures(idct, buffer)) + return false; + + if (!init_vertex_buffers(idct, buffer)) + return false; + + /* init state */ + buffer->viewport[0].scale[0] = buffer->textures.individual.intermediate->width0; + buffer->viewport[0].scale[1] = buffer->textures.individual.intermediate->height0; + + buffer->viewport[1].scale[0] = buffer->destination->width0; + buffer->viewport[1].scale[1] = buffer->destination->height0; + + buffer->fb_state[0].width = buffer->textures.individual.intermediate->width0; + buffer->fb_state[0].height = buffer->textures.individual.intermediate->height0; + + buffer->fb_state[0].nr_cbufs = NR_RENDER_TARGETS; + for(i = 0; i < NR_RENDER_TARGETS; ++i) { + memset(&template, 0, sizeof(template)); + template.format = buffer->textures.individual.intermediate->format; + template.u.tex.first_layer = i; + template.u.tex.last_layer = i; + template.usage = PIPE_BIND_RENDER_TARGET; + buffer->fb_state[0].cbufs[i] = idct->pipe->create_surface( + idct->pipe, buffer->textures.individual.intermediate, + &template); + } + + buffer->fb_state[1].width = buffer->destination->width0; + buffer->fb_state[1].height = buffer->destination->height0; + + buffer->fb_state[1].nr_cbufs = 1; + + memset(&template, 0, sizeof(template)); + template.format = buffer->destination->format; + template.usage = PIPE_BIND_RENDER_TARGET; + buffer->fb_state[1].cbufs[0] = idct->pipe->create_surface( + idct->pipe, buffer->destination, &template); + + for(i = 0; i < 2; ++i) { + buffer->viewport[i].scale[2] = 1; + buffer->viewport[i].scale[3] = 1; + buffer->viewport[i].translate[0] = 0; + buffer->viewport[i].translate[1] = 0; + buffer->viewport[i].translate[2] = 0; + buffer->viewport[i].translate[3] = 0; + + buffer->fb_state[i].zsbuf = NULL; + } + + return true; +} + +void +vl_idct_cleanup_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + unsigned i; + + assert(buffer); + + for(i = 0; i < NR_RENDER_TARGETS; ++i) { + idct->pipe->surface_destroy(idct->pipe, buffer->fb_state[0].cbufs[i]); + } + + idct->pipe->surface_destroy(idct->pipe, buffer->fb_state[1].cbufs[0]); + + cleanup_textures(idct, buffer); + cleanup_vertex_buffers(idct, buffer); +} + +void +vl_idct_map_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + assert(idct); + + struct pipe_box rect = + { + 0, 0, 0, + buffer->textures.individual.source->width0, + buffer->textures.individual.source->height0, + 1 + }; + + buffer->tex_transfer = idct->pipe->get_transfer + ( + idct->pipe, buffer->textures.individual.source, + 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &rect + ); + + buffer->texels = idct->pipe->transfer_map(idct->pipe, buffer->tex_transfer); + + vl_vb_map(&buffer->blocks, idct->pipe); +} + +void +vl_idct_add_block(struct vl_idct_buffer *buffer, unsigned x, unsigned y, short *block) +{ + struct vertex2s v; + unsigned tex_pitch; + short *texels; + + unsigned i; + + assert(buffer); + + tex_pitch = buffer->tex_transfer->stride / sizeof(short); + texels = buffer->texels + y * tex_pitch * BLOCK_HEIGHT + x * BLOCK_WIDTH; + + for (i = 0; i < BLOCK_HEIGHT; ++i) + memcpy(texels + i * tex_pitch, block + i * BLOCK_WIDTH, BLOCK_WIDTH * sizeof(short)); + + v.x = x; + v.y = y; + vl_vb_add_block(&buffer->blocks, &v); +} + +void +vl_idct_unmap_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + assert(idct && buffer); + + idct->pipe->transfer_unmap(idct->pipe, buffer->tex_transfer); + idct->pipe->transfer_destroy(idct->pipe, buffer->tex_transfer); + vl_vb_unmap(&buffer->blocks, idct->pipe); +} + +void +vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer) +{ + unsigned num_verts; + + assert(idct); + + num_verts = vl_vb_restart(&buffer->blocks); + + if(num_verts > 0) { + + idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state); + idct->pipe->set_vertex_buffers(idct->pipe, 2, buffer->vertex_bufs.all); + idct->pipe->bind_vertex_elements_state(idct->pipe, idct->vertex_elems_state); + + /* first stage */ + idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state[0]); + idct->pipe->set_viewport_state(idct->pipe, &buffer->viewport[0]); + idct->pipe->set_fragment_sampler_views(idct->pipe, 2, buffer->sampler_views.stage[0]); + idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers.stage[0]); + idct->pipe->bind_vs_state(idct->pipe, idct->matrix_vs); + idct->pipe->bind_fs_state(idct->pipe, idct->matrix_fs); + util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_verts); + + /* second stage */ + idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state[1]); + idct->pipe->set_viewport_state(idct->pipe, &buffer->viewport[1]); + idct->pipe->set_fragment_sampler_views(idct->pipe, 2, buffer->sampler_views.stage[1]); + idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers.stage[1]); + idct->pipe->bind_vs_state(idct->pipe, idct->transpose_vs); + idct->pipe->bind_fs_state(idct->pipe, idct->transpose_fs); + util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_verts); + } +} diff --git a/src/gallium/auxiliary/vl/vl_idct.h b/src/gallium/auxiliary/vl/vl_idct.h new file mode 100644 index 00000000000..fcba75a7607 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_idct.h @@ -0,0 +1,124 @@ +/************************************************************************** + * + * Copyright 2010 Christian König + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_idct_h +#define vl_idct_h + +#include <pipe/p_state.h> +#include "vl_vertex_buffers.h" + +struct vl_idct +{ + struct pipe_context *pipe; + + unsigned buffer_width; + unsigned buffer_height; + + unsigned max_blocks; + + void *rs_state; + void *vertex_elems_state; + + union + { + void *all[4]; + void *stage[2][2]; + struct { + void *matrix, *source; + void *transpose, *intermediate; + } individual; + } samplers; + + void *matrix_vs, *transpose_vs; + void *matrix_fs, *transpose_fs; + + struct pipe_resource *matrix; + struct pipe_vertex_buffer quad; + + unsigned vertex_buffer_stride; +}; + +struct vl_idct_buffer +{ + struct pipe_viewport_state viewport[2]; + struct pipe_framebuffer_state fb_state[2]; + + struct pipe_resource *destination; + + union + { + struct pipe_sampler_view *all[4]; + struct pipe_sampler_view *stage[2][2]; + struct { + struct pipe_sampler_view *matrix, *source; + struct pipe_sampler_view *transpose, *intermediate; + } individual; + } sampler_views; + + union + { + struct pipe_resource *all[4]; + struct pipe_resource *stage[2][2]; + struct { + struct pipe_resource *matrix, *source; + struct pipe_resource *transpose, *intermediate; + } individual; + } textures; + + union + { + struct pipe_vertex_buffer all[2]; + struct { struct pipe_vertex_buffer quad, pos; } individual; + } vertex_bufs; + + struct vl_vertex_buffer blocks; + + struct pipe_transfer *tex_transfer; + short *texels; +}; + +struct pipe_resource *vl_idct_upload_matrix(struct pipe_context *pipe); + +bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe, + unsigned buffer_width, unsigned buffer_height, + struct pipe_resource *matrix); + +void vl_idct_cleanup(struct vl_idct *idct); + +bool vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer, struct pipe_resource *dst); + +void vl_idct_cleanup_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer); + +void vl_idct_map_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer); + +void vl_idct_add_block(struct vl_idct_buffer *buffer, unsigned x, unsigned y, short *block); + +void vl_idct_unmap_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer); + +void vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer); + +#endif diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c new file mode 100644 index 00000000000..de83b6a5338 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c @@ -0,0 +1,1093 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl_mpeg12_mc_renderer.h" +#include "util/u_draw.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <util/u_inlines.h> +#include <util/u_format.h> +#include <util/u_math.h> +#include <util/u_memory.h> +#include <util/u_keymap.h> +#include <util/u_sampler.h> +#include <util/u_draw.h> +#include <tgsi/tgsi_ureg.h> + +#define DEFAULT_BUF_ALIGNMENT 1 +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define BLOCK_WIDTH 8 +#define BLOCK_HEIGHT 8 + +struct vertex_stream +{ + struct vertex2s pos; + struct vertex2s mv[4]; + struct { + int8_t y; + int8_t cr; + int8_t cb; + int8_t flag; + } eb[2][2]; +}; + +enum VS_INPUT +{ + VS_I_RECT, + VS_I_VPOS, + VS_I_MV0, + VS_I_MV1, + VS_I_MV2, + VS_I_MV3, + VS_I_EB_0_0, + VS_I_EB_0_1, + VS_I_EB_1_0, + VS_I_EB_1_1, + + NUM_VS_INPUTS +}; + +enum VS_OUTPUT +{ + VS_O_VPOS, + VS_O_LINE, + VS_O_TEX0, + VS_O_TEX1, + VS_O_TEX2, + VS_O_EB_0, + VS_O_EB_1, + VS_O_INFO, + VS_O_MV0, + VS_O_MV1, + VS_O_MV2, + VS_O_MV3 +}; + +static const unsigned const_empty_block_mask_420[3][2][2] = { + { { 0x20, 0x10 }, { 0x08, 0x04 } }, + { { 0x02, 0x02 }, { 0x02, 0x02 } }, + { { 0x01, 0x01 }, { 0x01, 0x01 } } +}; + +static void * +create_vert_shader(struct vl_mpeg12_mc_renderer *r) +{ + struct ureg_program *shader; + struct ureg_src block_scale, mv_scale; + struct ureg_src vrect, vpos, eb[2][2], vmv[4]; + struct ureg_dst t_vpos, t_vtex, t_vmv; + struct ureg_dst o_vpos, o_line, o_vtex[3], o_eb[2], o_vmv[4], o_info; + unsigned i, label; + + shader = ureg_create(TGSI_PROCESSOR_VERTEX); + if (!shader) + return NULL; + + t_vpos = ureg_DECL_temporary(shader); + t_vtex = ureg_DECL_temporary(shader); + t_vmv = ureg_DECL_temporary(shader); + + vrect = ureg_DECL_vs_input(shader, VS_I_RECT); + vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); + eb[0][0] = ureg_DECL_vs_input(shader, VS_I_EB_0_0); + eb[1][0] = ureg_DECL_vs_input(shader, VS_I_EB_1_0); + eb[0][1] = ureg_DECL_vs_input(shader, VS_I_EB_0_1); + eb[1][1] = ureg_DECL_vs_input(shader, VS_I_EB_1_1); + + o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); + o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE); + o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0); + o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1); + o_vtex[2] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2); + o_eb[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0); + o_eb[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1); + o_info = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_INFO); + + for (i = 0; i < 4; ++i) { + vmv[i] = ureg_DECL_vs_input(shader, VS_I_MV0 + i); + o_vmv[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i); + } + + /* + * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height) + * mv_scale = 0.5 / (dst.width, dst.height); + * + * t_vpos = (vpos + vrect) * block_scale + * o_vpos.xy = t_vpos + * o_vpos.zw = vpos + * + * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0] + * + * o_frame_pred = frame_pred + * o_info.x = ref_frames + * o_info.y = ref_frames > 0 + * o_info.z = bkwd_pred + * + * // Apply motion vectors + * o_vmv[0..count] = t_vpos + vmv[0..count] * mv_scale + * + * o_line.xy = vrect * 8 + * o_line.z = interlaced + * + * if(eb[0][0].w) { //interlaced + * t_vtex.x = vrect.x + * t_vtex.y = vrect.y * 0.5 + * t_vtex += vpos + * + * o_vtex[0].xy = t_vtex * block_scale + * + * t_vtex.y += 0.5 + * o_vtex[1].xy = t_vtex * block_scale + * } else { + * o_vtex[0..1].xy = t_vpos + * } + * o_vtex[2].xy = t_vpos + * + */ + block_scale = ureg_imm2f(shader, + (float)MACROBLOCK_WIDTH / r->buffer_width, + (float)MACROBLOCK_HEIGHT / r->buffer_height); + + mv_scale = ureg_imm2f(shader, + 0.5f / r->buffer_width, + 0.5f / r->buffer_height); + + ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect); + ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale); + ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos)); + ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos); + + ureg_CMP(shader, ureg_writemask(o_eb[0], TGSI_WRITEMASK_XYZ), + ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)), + eb[0][1], eb[0][0]); + ureg_CMP(shader, ureg_writemask(o_eb[1], TGSI_WRITEMASK_XYZ), + ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)), + eb[1][1], eb[1][0]); + + ureg_MOV(shader, ureg_writemask(o_info, TGSI_WRITEMASK_X), + ureg_scalar(eb[1][1], TGSI_SWIZZLE_W)); + ureg_SGE(shader, ureg_writemask(o_info, TGSI_WRITEMASK_Y), + ureg_scalar(eb[1][1], TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.0f)); + ureg_MOV(shader, ureg_writemask(o_info, TGSI_WRITEMASK_Z), + ureg_scalar(eb[1][0], TGSI_SWIZZLE_W)); + + ureg_MAD(shader, ureg_writemask(o_vmv[0], TGSI_WRITEMASK_XY), mv_scale, vmv[0], ureg_src(t_vpos)); + ureg_MAD(shader, ureg_writemask(o_vmv[2], TGSI_WRITEMASK_XY), mv_scale, vmv[2], ureg_src(t_vpos)); + + ureg_CMP(shader, ureg_writemask(t_vmv, TGSI_WRITEMASK_XY), + ureg_negate(ureg_scalar(eb[0][1], TGSI_SWIZZLE_W)), + vmv[0], vmv[1]); + ureg_MAD(shader, ureg_writemask(o_vmv[1], TGSI_WRITEMASK_XY), mv_scale, ureg_src(t_vmv), ureg_src(t_vpos)); + + ureg_CMP(shader, ureg_writemask(t_vmv, TGSI_WRITEMASK_XY), + ureg_negate(ureg_scalar(eb[0][1], TGSI_SWIZZLE_W)), + vmv[2], vmv[3]); + ureg_MAD(shader, ureg_writemask(o_vmv[3], TGSI_WRITEMASK_XY), mv_scale, ureg_src(t_vmv), ureg_src(t_vpos)); + + ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos)); + ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos)); + ureg_MOV(shader, ureg_writemask(o_vtex[2], TGSI_WRITEMASK_XY), ureg_src(t_vpos)); + + ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X), ureg_scalar(vrect, TGSI_SWIZZLE_Y)); + ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y), + vrect, ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2)); + + ureg_IF(shader, ureg_scalar(eb[0][0], TGSI_SWIZZLE_W), &label); + + ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect); + ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f)); + ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex)); + ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale); + ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f)); + ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale); + + ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X), + ureg_scalar(vrect, TGSI_SWIZZLE_Y), + ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2)); + + ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); + ureg_ENDIF(shader); + + ureg_release_temporary(shader, t_vtex); + ureg_release_temporary(shader, t_vpos); + ureg_release_temporary(shader, t_vmv); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, r->pipe); +} + +static struct ureg_dst +calc_field(struct ureg_program *shader) +{ + struct ureg_dst tmp; + struct ureg_src line; + + tmp = ureg_DECL_temporary(shader); + + line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR); + + /* + * line.x going from 0 to 1 if not interlaced + * line.x going from 0 to 8 in steps of 0.5 if interlaced + * line.y going from 0 to 8 in steps of 0.5 + * + * tmp.xy = fraction(line) + * tmp.xy = tmp.xy >= 0.5 ? 1 : 0 + */ + ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), line); + ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(shader, 0.5f)); + + return tmp; +} + +static struct ureg_dst +fetch_ycbcr(struct vl_mpeg12_mc_renderer *r, struct ureg_program *shader, struct ureg_dst field) +{ + struct ureg_src tc[3], sampler[3], eb[2]; + struct ureg_dst texel, t_tc, t_eb_info; + unsigned i, label; + + texel = ureg_DECL_temporary(shader); + t_tc = ureg_DECL_temporary(shader); + t_eb_info = ureg_DECL_temporary(shader); + + tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0, TGSI_INTERPOLATE_LINEAR); + tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1, TGSI_INTERPOLATE_LINEAR); + tc[2] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2, TGSI_INTERPOLATE_LINEAR); + + eb[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0, TGSI_INTERPOLATE_CONSTANT); + eb[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1, TGSI_INTERPOLATE_CONSTANT); + + for (i = 0; i < 3; ++i) { + sampler[i] = ureg_DECL_sampler(shader, i); + } + + /* + * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0]) + * texel.cb = tex(tc[2], sampler[1]) + * texel.cr = tex(tc[2], sampler[2]) + */ + + ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY), + ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)), + tc[1], tc[0]); + + ureg_CMP(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ), + ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)), + eb[1], eb[0]); + + /* r600g is ignoring TGSI_INTERPOLATE_CONSTANT, just workaround this */ + ureg_SLT(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ), ureg_src(t_eb_info), ureg_imm1f(shader, 0.5f)); + + ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.0f)); + for (i = 0; i < 3; ++i) { + ureg_IF(shader, ureg_scalar(ureg_src(t_eb_info), TGSI_SWIZZLE_X + i), &label); + + /* Nouveau can't writemask tex dst regs (yet?), so this won't work anymore on nvidia hardware */ + if(i==0 || r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444) { + ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, ureg_src(t_tc), sampler[i]); + } else { + ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, tc[2], sampler[i]); + } + + ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); + ureg_ENDIF(shader); + } + + ureg_release_temporary(shader, t_tc); + ureg_release_temporary(shader, t_eb_info); + + return texel; +} + +static struct ureg_dst +fetch_ref(struct ureg_program *shader, struct ureg_dst field) +{ + struct ureg_src info; + struct ureg_src tc[4], sampler[2]; + struct ureg_dst ref[2], result; + unsigned i, intra_label, bi_label, label; + + info = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_INFO, TGSI_INTERPOLATE_CONSTANT); + + for (i = 0; i < 4; ++i) + tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR); + + for (i = 0; i < 2; ++i) { + sampler[i] = ureg_DECL_sampler(shader, i + 3); + ref[i] = ureg_DECL_temporary(shader); + } + + result = ureg_DECL_temporary(shader); + + ureg_MOV(shader, ureg_writemask(result, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.5f)); + + ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_Y), &intra_label); + ureg_CMP(shader, ureg_writemask(ref[0], TGSI_WRITEMASK_XY), + ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), + tc[1], tc[0]); + + ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_X), &bi_label); + + /* + * result = tex(field.z ? tc[1] : tc[0], sampler[bkwd_pred ? 1 : 0]) + */ + ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_Z), &label); + ureg_TEX(shader, result, TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[1]); + ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); + ureg_ELSE(shader, &label); + ureg_TEX(shader, result, TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[0]); + ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); + ureg_ENDIF(shader); + + ureg_fixup_label(shader, bi_label, ureg_get_instruction_number(shader)); + ureg_ELSE(shader, &bi_label); + + /* + * if (field.z) + * ref[0..1] = tex(tc[0..1], sampler[0..1]) + * else + * ref[0..1] = tex(tc[2..3], sampler[0..1]) + */ + ureg_CMP(shader, ureg_writemask(ref[1], TGSI_WRITEMASK_XY), + ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), + tc[3], tc[2]); + ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[0]); + ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, ureg_src(ref[1]), sampler[1]); + + ureg_LRP(shader, ureg_writemask(result, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.5f), + ureg_src(ref[0]), ureg_src(ref[1])); + + ureg_fixup_label(shader, bi_label, ureg_get_instruction_number(shader)); + ureg_ENDIF(shader); + ureg_fixup_label(shader, intra_label, ureg_get_instruction_number(shader)); + ureg_ENDIF(shader); + + for (i = 0; i < 2; ++i) + ureg_release_temporary(shader, ref[i]); + + return result; +} + +static void * +create_frag_shader(struct vl_mpeg12_mc_renderer *r) +{ + struct ureg_program *shader; + struct ureg_dst result; + struct ureg_dst field, texel; + struct ureg_dst fragment; + + shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!shader) + return NULL; + + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + field = calc_field(shader); + texel = fetch_ycbcr(r, shader, field); + + result = fetch_ref(shader, field); + + ureg_ADD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(texel), ureg_src(result)); + + ureg_release_temporary(shader, field); + ureg_release_temporary(shader, texel); + ureg_release_temporary(shader, result); + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, r->pipe); +} + +static bool +init_pipe_state(struct vl_mpeg12_mc_renderer *r) +{ + struct pipe_sampler_state sampler; + struct pipe_rasterizer_state rs_state; + unsigned filters[5]; + unsigned i; + + assert(r); + + r->viewport.scale[0] = r->buffer_width; + r->viewport.scale[1] = r->buffer_height; + r->viewport.scale[2] = 1; + r->viewport.scale[3] = 1; + r->viewport.translate[0] = 0; + r->viewport.translate[1] = 0; + r->viewport.translate[2] = 0; + r->viewport.translate[3] = 0; + + r->fb_state.width = r->buffer_width; + r->fb_state.height = r->buffer_height; + r->fb_state.nr_cbufs = 1; + r->fb_state.zsbuf = NULL; + + /* Luma filter */ + filters[0] = PIPE_TEX_FILTER_NEAREST; + /* Chroma filters */ + if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 || true) { //TODO + filters[1] = PIPE_TEX_FILTER_NEAREST; + filters[2] = PIPE_TEX_FILTER_NEAREST; + } + else { + filters[1] = PIPE_TEX_FILTER_LINEAR; + filters[2] = PIPE_TEX_FILTER_LINEAR; + } + /* Fwd, bkwd ref filters */ + filters[3] = PIPE_TEX_FILTER_LINEAR; + filters[4] = PIPE_TEX_FILTER_LINEAR; + + for (i = 0; i < 5; ++i) { + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER; + sampler.min_img_filter = filters[i]; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = filters[i]; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + /*sampler.shadow_ambient = ; */ + /*sampler.lod_bias = ; */ + sampler.min_lod = 0; + /*sampler.max_lod = ; */ + sampler.border_color[0] = 0.0f; + sampler.border_color[1] = 0.0f; + sampler.border_color[2] = 0.0f; + sampler.border_color[3] = 0.0f; + /*sampler.max_anisotropy = ; */ + r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler); + } + + memset(&rs_state, 0, sizeof(rs_state)); + /*rs_state.sprite_coord_enable */ + rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; + rs_state.point_quad_rasterization = true; + rs_state.point_size = BLOCK_WIDTH; + rs_state.gl_rasterization_rules = true; + r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state); + + return true; +} + +static void +cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r) +{ + unsigned i; + + assert(r); + + for (i = 0; i < 5; ++i) + r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]); + + r->pipe->delete_rasterizer_state(r->pipe, r->rs_state); +} + +static bool +init_buffers(struct vl_mpeg12_mc_renderer *r) +{ + struct pipe_resource *idct_matrix; + struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; + + const unsigned mbw = + align(r->buffer_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; + const unsigned mbh = + align(r->buffer_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; + + unsigned i, chroma_width, chroma_height; + + assert(r); + + r->macroblocks_per_batch = + mbw * (r->bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE ? mbh : 1); + + if (!(idct_matrix = vl_idct_upload_matrix(r->pipe))) + return false; + + if (!vl_idct_init(&r->idct_luma, r->pipe, r->buffer_width, r->buffer_height, idct_matrix)) + return false; + + if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { + chroma_width = r->buffer_width / 2; + chroma_height = r->buffer_height / 2; + } else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) { + chroma_width = r->buffer_width; + chroma_height = r->buffer_height / 2; + } else { + chroma_width = r->buffer_width; + chroma_height = r->buffer_height; + } + + if(!vl_idct_init(&r->idct_chroma, r->pipe, chroma_width, chroma_height, idct_matrix)) + return false; + + memset(&vertex_elems, 0, sizeof(vertex_elems)); + + vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); + r->quad = vl_vb_upload_quads(r->pipe, r->macroblocks_per_batch); + + /* Position element */ + vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; + + for (i = 0; i < 4; ++i) + /* motion vector 0..4 element */ + vertex_elems[VS_I_MV0 + i].src_format = PIPE_FORMAT_R16G16_SSCALED; + + /* y, cr, cb empty block element top left block */ + vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; + + /* y, cr, cb empty block element top right block */ + vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; + + /* y, cr, cb empty block element bottom left block */ + vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; + + /* y, cr, cb empty block element bottom right block */ + vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED; + + r->vertex_stream_stride = vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 9, 1); + + r->vertex_elems_state = r->pipe->create_vertex_elements_state( + r->pipe, NUM_VS_INPUTS, vertex_elems); + + if (r->vertex_elems_state == NULL) + return false; + + r->vs = create_vert_shader(r); + r->fs = create_frag_shader(r); + + if (r->vs == NULL || r->fs == NULL) + return false; + + return true; +} + +static void +cleanup_buffers(struct vl_mpeg12_mc_renderer *r) +{ + assert(r); + + r->pipe->delete_vs_state(r->pipe, r->vs); + r->pipe->delete_fs_state(r->pipe, r->fs); + + vl_idct_cleanup(&r->idct_luma); + vl_idct_cleanup(&r->idct_chroma); + + r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems_state); +} + +static struct pipe_sampler_view +*find_or_create_sampler_view(struct vl_mpeg12_mc_renderer *r, struct pipe_surface *surface) +{ + struct pipe_sampler_view *sampler_view; + assert(r); + assert(surface); + + sampler_view = (struct pipe_sampler_view*)util_keymap_lookup(r->texview_map, &surface); + if (!sampler_view) { + struct pipe_sampler_view templat; + boolean added_to_map; + + u_sampler_view_default_template(&templat, surface->texture, + surface->texture->format); + sampler_view = r->pipe->create_sampler_view(r->pipe, surface->texture, + &templat); + if (!sampler_view) + return NULL; + + added_to_map = util_keymap_insert(r->texview_map, &surface, + sampler_view, r->pipe); + assert(added_to_map); + } + + return sampler_view; +} + +static void +get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex2s mv[4]) +{ + switch (mb->mb_type) { + case PIPE_MPEG12_MACROBLOCK_TYPE_BI: + { + if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { + mv[2].x = mb->pmv[0][1][0]; + mv[2].y = mb->pmv[0][1][1]; + + } else { + mv[2].x = mb->pmv[0][1][0]; + mv[2].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4); + + mv[3].x = mb->pmv[1][1][0]; + mv[3].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4); + + if(mb->mvfs[0][1]) mv[2].y += 2; + if(!mb->mvfs[1][1]) mv[3].y -= 2; + } + + /* fall-through */ + } + case PIPE_MPEG12_MACROBLOCK_TYPE_FWD: + case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD: + { + if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) { + + if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { + mv[0].x = mb->pmv[0][1][0]; + mv[0].y = mb->pmv[0][1][1]; + + } else { + mv[0].x = mb->pmv[0][1][0]; + mv[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4); + + mv[1].x = mb->pmv[1][1][0]; + mv[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4); + + if(mb->mvfs[0][1]) mv[0].y += 2; + if(!mb->mvfs[1][1]) mv[1].y -= 2; + } + + } else { + + if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) { + mv[0].x = mb->pmv[0][0][0]; + mv[0].y = mb->pmv[0][0][1]; + + } else { + mv[0].x = mb->pmv[0][0][0]; + mv[0].y = mb->pmv[0][0][1] - (mb->pmv[0][0][1] % 4); + + mv[1].x = mb->pmv[1][0][0]; + mv[1].y = mb->pmv[1][0][1] - (mb->pmv[1][0][1] % 4); + + if(mb->mvfs[0][0]) mv[0].y += 2; + if(!mb->mvfs[1][0]) mv[1].y -= 2; + } + } + } + default: + break; + } +} + +static void +grab_vectors(struct vl_mpeg12_mc_renderer *r, + struct vl_mpeg12_mc_buffer *buffer, + struct pipe_mpeg12_macroblock *mb) +{ + struct vertex_stream stream; + + unsigned i, j; + + assert(r); + assert(mb); + + stream.pos.x = mb->mbx; + stream.pos.y = mb->mby; + for ( i = 0; i < 2; ++i) { + for ( j = 0; j < 2; ++j) { + stream.eb[i][j].y = !(mb->cbp & (*r->empty_block_mask)[0][i][j]); + stream.eb[i][j].cr = !(mb->cbp & (*r->empty_block_mask)[1][i][j]); + stream.eb[i][j].cb = !(mb->cbp & (*r->empty_block_mask)[2][i][j]); + } + } + stream.eb[0][0].flag = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD; + stream.eb[0][1].flag = mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME; + stream.eb[1][0].flag = mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD; + switch (mb->mb_type) { + case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA: + stream.eb[1][1].flag = -1; + break; + + case PIPE_MPEG12_MACROBLOCK_TYPE_FWD: + case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD: + stream.eb[1][1].flag = 1; + break; + + case PIPE_MPEG12_MACROBLOCK_TYPE_BI: + stream.eb[1][1].flag = 0; + break; + + default: + assert(0); + } + + get_motion_vectors(mb, stream.mv); + vl_vb_add_block(&buffer->vertex_stream, &stream); +} + +static void +grab_blocks(struct vl_mpeg12_mc_renderer *r, + struct vl_mpeg12_mc_buffer *buffer, + unsigned mbx, unsigned mby, + unsigned cbp, short *blocks) +{ + unsigned tb = 0; + unsigned x, y; + + assert(r); + assert(blocks); + + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x, ++tb) { + if (cbp & (*r->empty_block_mask)[0][y][x]) { + vl_idct_add_block(&buffer->idct_y, mbx * 2 + x, mby * 2 + y, blocks); + blocks += BLOCK_WIDTH * BLOCK_HEIGHT; + } + } + } + + /* TODO: Implement 422, 444 */ + assert(r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); + + for (tb = 1; tb < 3; ++tb) { + if (cbp & (*r->empty_block_mask)[tb][0][0]) { + if(tb == 1) + vl_idct_add_block(&buffer->idct_cb, mbx, mby, blocks); + else + vl_idct_add_block(&buffer->idct_cr, mbx, mby, blocks); + blocks += BLOCK_WIDTH * BLOCK_HEIGHT; + } + } +} + +static void +grab_macroblock(struct vl_mpeg12_mc_renderer *r, + struct vl_mpeg12_mc_buffer *buffer, + struct pipe_mpeg12_macroblock *mb) +{ + assert(r); + assert(mb); + assert(mb->blocks); + assert(buffer->num_macroblocks < r->macroblocks_per_batch); + + grab_vectors(r, buffer, mb); + grab_blocks(r, buffer, mb->mbx, mb->mby, mb->cbp, mb->blocks); + + ++buffer->num_macroblocks; +} + +static void +texview_map_delete(const struct keymap *map, + const void *key, void *data, + void *user) +{ + struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data; + + assert(map); + assert(key); + assert(data); + assert(user); + + pipe_sampler_view_reference(&sv, NULL); +} + +bool +vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer, + struct pipe_context *pipe, + unsigned buffer_width, + unsigned buffer_height, + enum pipe_video_chroma_format chroma_format, + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode) +{ + assert(renderer); + assert(pipe); + + /* TODO: Implement other policies */ + assert(bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE); + + memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer)); + + renderer->pipe = pipe; + renderer->buffer_width = buffer_width; + renderer->buffer_height = buffer_height; + renderer->chroma_format = chroma_format; + renderer->bufmode = bufmode; + + /* TODO: Implement 422, 444 */ + assert(chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); + renderer->empty_block_mask = &const_empty_block_mask_420; + + renderer->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1, + texview_map_delete); + if (!renderer->texview_map) + return false; + + if (!init_pipe_state(renderer)) + goto error_pipe_state; + + if (!init_buffers(renderer)) + goto error_buffers; + + return true; + +error_buffers: + cleanup_pipe_state(renderer); + +error_pipe_state: + util_delete_keymap(renderer->texview_map, renderer->pipe); + return false; +} + +void +vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer) +{ + assert(renderer); + + util_delete_keymap(renderer->texview_map, renderer->pipe); + cleanup_pipe_state(renderer); + cleanup_buffers(renderer); +} + +bool +vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +{ + struct pipe_resource template; + struct pipe_sampler_view sampler_view; + + unsigned i; + + assert(renderer && buffer); + + buffer->surface = NULL; + buffer->past = NULL; + buffer->future = NULL; + buffer->num_macroblocks = 0; + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */ + template.format = PIPE_FORMAT_R16_SNORM; + template.last_level = 0; + template.width0 = renderer->buffer_width; + template.height0 = renderer->buffer_height; + template.depth0 = 1; + template.usage = PIPE_USAGE_STATIC; + template.bind = PIPE_BIND_SAMPLER_VIEW; + template.flags = 0; + + buffer->textures.individual.y = renderer->pipe->screen->resource_create(renderer->pipe->screen, &template); + + if (!vl_idct_init_buffer(&renderer->idct_luma, &buffer->idct_y, buffer->textures.individual.y)) + return false; + + if (renderer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { + template.width0 = renderer->buffer_width / 2; + template.height0 = renderer->buffer_height / 2; + } + else if (renderer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) + template.height0 = renderer->buffer_height / 2; + + buffer->textures.individual.cb = + renderer->pipe->screen->resource_create(renderer->pipe->screen, &template); + buffer->textures.individual.cr = + renderer->pipe->screen->resource_create(renderer->pipe->screen, &template); + + if (!vl_idct_init_buffer(&renderer->idct_chroma, &buffer->idct_cb, buffer->textures.individual.cb)) + return false; + + if (!vl_idct_init_buffer(&renderer->idct_chroma, &buffer->idct_cr, buffer->textures.individual.cr)) + return false; + + for (i = 0; i < 3; ++i) { + u_sampler_view_default_template(&sampler_view, + buffer->textures.all[i], + buffer->textures.all[i]->format); + sampler_view.swizzle_r = i == 0 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO; + sampler_view.swizzle_g = i == 1 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO; + sampler_view.swizzle_b = i == 2 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO; + sampler_view.swizzle_a = PIPE_SWIZZLE_ONE; + buffer->sampler_views.all[i] = renderer->pipe->create_sampler_view( + renderer->pipe, buffer->textures.all[i], &sampler_view); + } + + buffer->vertex_bufs.individual.quad.stride = renderer->quad.stride; + buffer->vertex_bufs.individual.quad.max_index = renderer->quad.max_index; + buffer->vertex_bufs.individual.quad.buffer_offset = renderer->quad.buffer_offset; + pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, renderer->quad.buffer); + + buffer->vertex_bufs.individual.stream = vl_vb_init( + &buffer->vertex_stream, renderer->pipe, renderer->macroblocks_per_batch, + renderer->vertex_stream_stride); + + return true; +} + +void +vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +{ + unsigned i; + + assert(renderer && buffer); + + for (i = 0; i < 3; ++i) { + pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL); + pipe_resource_reference(&buffer->vertex_bufs.all[i].buffer, NULL); + pipe_resource_reference(&buffer->textures.all[i], NULL); + } + + pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, NULL); + vl_vb_cleanup(&buffer->vertex_stream); + + vl_idct_cleanup_buffer(&renderer->idct_luma, &buffer->idct_y); + vl_idct_cleanup_buffer(&renderer->idct_chroma, &buffer->idct_cb); + vl_idct_cleanup_buffer(&renderer->idct_chroma, &buffer->idct_cr); + + pipe_surface_reference(&buffer->surface, NULL); + pipe_surface_reference(&buffer->past, NULL); + pipe_surface_reference(&buffer->future, NULL); +} + +void +vl_mpeg12_mc_map_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +{ + assert(renderer && buffer); + + vl_idct_map_buffers(&renderer->idct_luma, &buffer->idct_y); + vl_idct_map_buffers(&renderer->idct_chroma, &buffer->idct_cr); + vl_idct_map_buffers(&renderer->idct_chroma, &buffer->idct_cb); + + vl_vb_map(&buffer->vertex_stream, renderer->pipe); +} + +void +vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer *renderer, + struct vl_mpeg12_mc_buffer *buffer, + struct pipe_surface *surface, + struct pipe_surface *past, + struct pipe_surface *future, + unsigned num_macroblocks, + struct pipe_mpeg12_macroblock *mpeg12_macroblocks, + struct pipe_fence_handle **fence) +{ + assert(renderer && buffer); + assert(surface); + assert(num_macroblocks); + assert(mpeg12_macroblocks); + + if (surface != buffer->surface) { + pipe_surface_reference(&buffer->surface, surface); + pipe_surface_reference(&buffer->past, past); + pipe_surface_reference(&buffer->future, future); + buffer->fence = fence; + } else { + /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ + assert(buffer->past == past); + assert(buffer->future == future); + } + + while (num_macroblocks) { + unsigned left_in_batch = renderer->macroblocks_per_batch - buffer->num_macroblocks; + unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch); + unsigned i; + + for (i = 0; i < num_to_submit; ++i) { + assert(mpeg12_macroblocks[i].base.codec == PIPE_VIDEO_CODEC_MPEG12); + grab_macroblock(renderer, buffer, &mpeg12_macroblocks[i]); + } + + num_macroblocks -= num_to_submit; + + if (buffer->num_macroblocks == renderer->macroblocks_per_batch) { + vl_mpeg12_mc_unmap_buffer(renderer, buffer); + vl_mpeg12_mc_renderer_flush(renderer, buffer); + pipe_surface_reference(&buffer->surface, surface); + pipe_surface_reference(&buffer->past, past); + pipe_surface_reference(&buffer->future, future); + vl_mpeg12_mc_map_buffer(renderer, buffer); + } + } +} + +void +vl_mpeg12_mc_unmap_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +{ + assert(renderer && buffer); + + vl_idct_unmap_buffers(&renderer->idct_luma, &buffer->idct_y); + vl_idct_unmap_buffers(&renderer->idct_chroma, &buffer->idct_cr); + vl_idct_unmap_buffers(&renderer->idct_chroma, &buffer->idct_cb); + + vl_vb_unmap(&buffer->vertex_stream, renderer->pipe); +} + +void +vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +{ + assert(renderer && buffer); + assert(buffer->num_macroblocks <= renderer->macroblocks_per_batch); + + if (buffer->num_macroblocks == 0) + return; + + vl_idct_flush(&renderer->idct_luma, &buffer->idct_y); + vl_idct_flush(&renderer->idct_chroma, &buffer->idct_cr); + vl_idct_flush(&renderer->idct_chroma, &buffer->idct_cb); + + vl_vb_restart(&buffer->vertex_stream); + + renderer->fb_state.cbufs[0] = buffer->surface; + renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state); + renderer->pipe->set_framebuffer_state(renderer->pipe, &renderer->fb_state); + renderer->pipe->set_viewport_state(renderer->pipe, &renderer->viewport); + renderer->pipe->set_vertex_buffers(renderer->pipe, 2, buffer->vertex_bufs.all); + renderer->pipe->bind_vertex_elements_state(renderer->pipe, renderer->vertex_elems_state); + + if (buffer->past) { + buffer->textures.individual.ref[0] = buffer->past->texture; + buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->past); + } else { + buffer->textures.individual.ref[0] = buffer->surface->texture; + buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->surface); + } + + if (buffer->future) { + buffer->textures.individual.ref[1] = buffer->future->texture; + buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->future); + } else { + buffer->textures.individual.ref[1] = buffer->surface->texture; + buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->surface); + } + + renderer->pipe->set_fragment_sampler_views(renderer->pipe, 5, buffer->sampler_views.all); + renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 5, renderer->samplers.all); + + renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs); + renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs); + util_draw_arrays(renderer->pipe, PIPE_PRIM_QUADS, 0, buffer->num_macroblocks * 4); + + renderer->pipe->flush(renderer->pipe, PIPE_FLUSH_RENDER_CACHE, buffer->fence); + + /* Next time we get this surface it may have new ref frames */ + pipe_surface_reference(&buffer->surface, NULL); + pipe_surface_reference(&buffer->past, NULL); + pipe_surface_reference(&buffer->future, NULL); + + buffer->num_macroblocks = 0; +} diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h new file mode 100644 index 00000000000..76d6e25ca36 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h @@ -0,0 +1,141 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_mpeg12_mc_renderer_h +#define vl_mpeg12_mc_renderer_h + +#include <pipe/p_compiler.h> +#include <pipe/p_state.h> +#include <pipe/p_video_state.h> +#include "vl_types.h" +#include "vl_idct.h" +#include "vl_vertex_buffers.h" + +struct pipe_context; +struct pipe_macroblock; +struct keymap; + +/* A slice is video-width (rounded up to a multiple of macroblock width) x macroblock height */ +enum VL_MPEG12_MC_RENDERER_BUFFER_MODE +{ + VL_MPEG12_MC_RENDERER_BUFFER_SLICE, /* Saves memory at the cost of smaller batches */ + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE /* Larger batches, more memory */ +}; + +struct vl_mpeg12_mc_renderer +{ + struct pipe_context *pipe; + unsigned buffer_width; + unsigned buffer_height; + enum pipe_video_chroma_format chroma_format; + const unsigned (*empty_block_mask)[3][2][2]; + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode; + unsigned macroblocks_per_batch; + + unsigned vertex_stream_stride; + + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state fb_state; + + struct vl_idct idct_luma, idct_chroma; + + void *vertex_elems_state; + void *rs_state; + + void *vs, *fs; + + struct pipe_vertex_buffer quad; + + union + { + void *all[5]; + struct { void *y, *cb, *cr, *ref[2]; } individual; + } samplers; + + struct keymap *texview_map; +}; + +struct vl_mpeg12_mc_buffer +{ + struct vl_idct_buffer idct_y, idct_cb, idct_cr; + + struct vl_vertex_buffer vertex_stream; + + union + { + struct pipe_sampler_view *all[5]; + struct { struct pipe_sampler_view *y, *cb, *cr, *ref[2]; } individual; + } sampler_views; + + union + { + struct pipe_resource *all[5]; + struct { struct pipe_resource *y, *cb, *cr, *ref[2]; } individual; + } textures; + + union + { + struct pipe_vertex_buffer all[2]; + struct { + struct pipe_vertex_buffer quad, stream; + } individual; + } vertex_bufs; + + struct pipe_surface *surface, *past, *future; + struct pipe_fence_handle **fence; + unsigned num_macroblocks; +}; + +bool vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer, + struct pipe_context *pipe, + unsigned picture_width, + unsigned picture_height, + enum pipe_video_chroma_format chroma_format, + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode); + +void vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer); + +bool vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); + +void vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); + +void vl_mpeg12_mc_map_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); + +void vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer *renderer, + struct vl_mpeg12_mc_buffer *buffer, + struct pipe_surface *surface, + struct pipe_surface *past, + struct pipe_surface *future, + unsigned num_macroblocks, + struct pipe_mpeg12_macroblock *mpeg12_macroblocks, + struct pipe_fence_handle **fence); + +void vl_mpeg12_mc_unmap_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); + +void vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); + +#endif /* vl_mpeg12_mc_renderer_h */ diff --git a/src/gallium/auxiliary/vl/vl_types.h b/src/gallium/auxiliary/vl/vl_types.h new file mode 100644 index 00000000000..9c745d73978 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_types.h @@ -0,0 +1,51 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_types_h +#define vl_types_h + +struct vertex2f +{ + float x, y; +}; + +struct vertex2s +{ + short x, y; +}; + +struct vertex4f +{ + float x, y, z, w; +}; + +struct quadf +{ + struct vertex2f bl, tl, tr, br; +}; + +#endif /* vl_types_h */ diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c new file mode 100644 index 00000000000..8599ed3533d --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c @@ -0,0 +1,183 @@ +/************************************************************************** + * + * Copyright 2010 Christian König + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <util/u_memory.h> +#include <util/u_inlines.h> +#include <util/u_format.h> +#include "vl_vertex_buffers.h" +#include "vl_types.h" + +/* vertices for a quad covering a block */ +static const struct quadf const_quad = { + {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f} +}; + +struct pipe_vertex_buffer +vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks) +{ + struct pipe_vertex_buffer quad; + struct pipe_transfer *buf_transfer; + struct quadf *v; + + unsigned i; + + assert(pipe); + assert(max_blocks); + + /* create buffer */ + quad.stride = sizeof(struct vertex2f); + quad.max_index = 4 * max_blocks - 1; + quad.buffer_offset = 0; + quad.buffer = pipe_buffer_create + ( + pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + sizeof(struct vertex2f) * 4 * max_blocks + ); + + if(!quad.buffer) + return quad; + + /* and fill it */ + v = pipe_buffer_map + ( + pipe, + quad.buffer, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &buf_transfer + ); + + for ( i = 0; i < max_blocks; ++i) + memcpy(v + i, &const_quad, sizeof(const_quad)); + + pipe_buffer_unmap(pipe, buf_transfer); + + return quad; +} + +struct pipe_vertex_element +vl_vb_get_quad_vertex_element(void) +{ + struct pipe_vertex_element element; + + /* setup rectangle element */ + element.src_offset = 0; + element.instance_divisor = 0; + element.vertex_buffer_index = 0; + element.src_format = PIPE_FORMAT_R32G32_FLOAT; + + return element; +} + +unsigned +vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, + unsigned vertex_buffer_index) +{ + unsigned i, size, offset = 0; + + assert(elements && num_elements); + + for ( i = 0; i < num_elements; ++i ) { + elements[i].src_offset = offset; + elements[i].instance_divisor = 0; + elements[i].vertex_buffer_index = vertex_buffer_index; + offset += util_format_get_blocksize(elements[i].src_format); + } + + return offset; +} + +struct pipe_vertex_buffer +vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, + unsigned max_blocks, unsigned stride) +{ + struct pipe_vertex_buffer buf; + + assert(buffer); + + buffer->num_verts = 0; + buffer->stride = stride; + + buf.stride = stride; + buf.max_index = 4 * max_blocks - 1; + buf.buffer_offset = 0; + buf.buffer = pipe_buffer_create + ( + pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + stride * 4 * max_blocks + ); + + pipe_resource_reference(&buffer->resource, buf.buffer); + + vl_vb_map(buffer, pipe); + + return buf; +} + +void +vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) +{ + assert(buffer && pipe); + + buffer->vectors = pipe_buffer_map + ( + pipe, + buffer->resource, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &buffer->transfer + ); +} + +void +vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) +{ + assert(buffer && pipe); + + pipe_buffer_unmap(pipe, buffer->transfer); +} + +unsigned +vl_vb_restart(struct vl_vertex_buffer *buffer) +{ + assert(buffer); + + unsigned todo = buffer->num_verts; + buffer->num_verts = 0; + return todo; +} + +void +vl_vb_cleanup(struct vl_vertex_buffer *buffer) +{ + assert(buffer); + + pipe_resource_reference(&buffer->resource, NULL); +} diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.h b/src/gallium/auxiliary/vl/vl_vertex_buffers.h new file mode 100644 index 00000000000..b8e8766ec50 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.h @@ -0,0 +1,78 @@ +/************************************************************************** + * + * Copyright 2010 Christian König + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +#ifndef vl_vertex_buffers_h +#define vl_vertex_buffers_h + +#include <assert.h> +#include <pipe/p_state.h> +#include "vl_types.h" + +struct vl_vertex_buffer +{ + unsigned num_verts; + unsigned stride; + struct pipe_resource *resource; + struct pipe_transfer *transfer; + void *vectors; +}; + +struct pipe_vertex_buffer vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks); + +struct pipe_vertex_element vl_vb_get_quad_vertex_element(void); + +unsigned vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, + unsigned vertex_buffer_index); + +struct pipe_vertex_buffer vl_vb_init(struct vl_vertex_buffer *buffer, + struct pipe_context *pipe, + unsigned max_blocks, unsigned stride); + +void vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); + +static inline void +vl_vb_add_block(struct vl_vertex_buffer *buffer, void *elements) +{ + void *pos; + unsigned i; + + assert(buffer); + + pos = buffer->vectors + buffer->num_verts * buffer->stride; + for(i = 0; i < 4; ++i) { + memcpy(pos, elements, buffer->stride); + pos += buffer->stride; + buffer->num_verts++; + } +} + +void vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); + +unsigned vl_vb_restart(struct vl_vertex_buffer *buffer); + +void vl_vb_cleanup(struct vl_vertex_buffer *buffer); + +#endif diff --git a/src/gallium/drivers/nv40/nv40_video_context.c b/src/gallium/drivers/nv40/nv40_video_context.c new file mode 100644 index 00000000000..e6e57ee787c --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_video_context.c @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "nv40_video_context.h" +#include <softpipe/sp_video_context.h> + +struct pipe_video_context * +nv40_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv) +{ + struct pipe_context *pipe; + + assert(screen); + + pipe = screen->context_create(screen, priv); + if (!pipe) + return NULL; + + return sp_video_create_ex(pipe, profile, chroma_format, width, height, + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE, + true); +} diff --git a/src/gallium/drivers/nv40/nv40_video_context.h b/src/gallium/drivers/nv40/nv40_video_context.h new file mode 100644 index 00000000000..64196caca72 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_video_context.h @@ -0,0 +1,38 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef __NV40_VIDEO_CONTEXT_H__ +#define __NV40_VIDEO_CONTEXT_H__ + +#include <pipe/p_video_context.h> + +struct pipe_video_context * +nv40_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv); + +#endif diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile index 46bb0823881..95da7782256 100644 --- a/src/gallium/drivers/nvfx/Makefile +++ b/src/gallium/drivers/nvfx/Makefile @@ -24,7 +24,8 @@ C_SOURCES = \ nvfx_surface.c \ nvfx_transfer.c \ nvfx_vbo.c \ - nvfx_vertprog.c + nvfx_vertprog.c \ + nvfx_video_context.c LIBRARY_INCLUDES = \ -I$(TOP)/src/gallium/drivers/nouveau/include diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index aa1e9567d31..15db574a1d0 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -6,6 +6,7 @@ #include "nouveau/nouveau_screen.h" #include "nouveau/nv_object.xml.h" #include "nvfx_context.h" +#include "nvfx_video_context.h" #include "nvfx_screen.h" #include "nvfx_resource.h" #include "nvfx_tex.h" @@ -455,6 +456,7 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_paramf = nvfx_screen_get_paramf; pscreen->is_format_supported = nvfx_screen_is_format_supported; pscreen->context_create = nvfx_create; + pscreen->video_context_create = nvfx_video_create; switch (dev->chipset & 0xf0) { case 0x30: diff --git a/src/gallium/drivers/nvfx/nvfx_state.h b/src/gallium/drivers/nvfx/nvfx_state.h index 8fafca1950c..15e1cbb1986 100644 --- a/src/gallium/drivers/nvfx/nvfx_state.h +++ b/src/gallium/drivers/nvfx/nvfx_state.h @@ -2,6 +2,7 @@ #define __NVFX_STATE_H__ #include "pipe/p_state.h" +#include "pipe/p_video_state.h" #include "tgsi/tgsi_scan.h" #include "nouveau/nouveau_statebuf.h" #include "util/u_dynarray.h" diff --git a/src/gallium/drivers/nvfx/nvfx_video_context.c b/src/gallium/drivers/nvfx/nvfx_video_context.c new file mode 100644 index 00000000000..58e1c0baa27 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_video_context.c @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "nvfx_video_context.h" +#include <softpipe/sp_video_context.h> + +struct pipe_video_context * +nvfx_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv) +{ + struct pipe_context *pipe; + + assert(screen); + + pipe = screen->context_create(screen, priv); + if (!pipe) + return NULL; + + return sp_video_create_ex(pipe, profile, chroma_format, width, height, + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE, + true, + PIPE_FORMAT_VUYX); +} diff --git a/src/gallium/drivers/nvfx/nvfx_video_context.h b/src/gallium/drivers/nvfx/nvfx_video_context.h new file mode 100644 index 00000000000..6619427cc29 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_video_context.h @@ -0,0 +1,38 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef __NVFX_VIDEO_CONTEXT_H__ +#define __NVFX_VIDEO_CONTEXT_H__ + +#include <pipe/p_video_context.h> + +struct pipe_video_context * +nvfx_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv); + +#endif diff --git a/src/gallium/drivers/r300/r300_video_context.c b/src/gallium/drivers/r300/r300_video_context.c new file mode 100644 index 00000000000..9fe6d6fcf25 --- /dev/null +++ b/src/gallium/drivers/r300/r300_video_context.c @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2009-2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * CooperYuan <[email protected]>, <[email protected]> + */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <pipe/p_defines.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <X11/Xlib.h> + +#include <fcntl.h> + +#include "radeon_buffer.h" +#include "radeon_r300.h" +#include "r300_screen.h" +#include "r300_texture.h" +#include "p_video_context.h" +#include "radeon_vl.h" +#include "softpipe/sp_winsys.h" +#include "softpipe/sp_texture.h" + +#include "r300_video_context.h" +#include <softpipe/sp_video_context.h> + +static void r300_mpeg12_destroy(struct pipe_video_context *vpipe) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + + assert(vpipe); + + ctx->pipe->bind_vs_state(ctx->pipe, NULL); + ctx->pipe->bind_fs_state(ctx->pipe, NULL); + + ctx->pipe->delete_blend_state(ctx->pipe, ctx->blend); + ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast); + ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa); + + pipe_video_surface_reference(&ctx->decode_target, NULL); + vl_compositor_cleanup(&ctx->compositor); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + + FREE(ctx); +} + +static void +r300_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe, + struct pipe_video_surface *past, + struct pipe_video_surface *future, + unsigned num_macroblocks, + struct pipe_macroblock *macroblocks, + struct pipe_fence_handle **fence) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + struct pipe_mpeg12_macroblock *mpeg12_macroblocks = + (struct pipe_mpeg12_macroblock*)macroblocks; + + assert(vpipe); + assert(num_macroblocks); + assert(macroblocks); + assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12); + assert(ctx->decode_target); + + vl_mpeg12_mc_renderer_render_macroblocks( + &ctx->mc_renderer, + r300_video_surface(ctx->decode_target)->tex, + past ? r300_video_surface(past)->tex : NULL, + future ? r300_video_surface(future)->tex : NULL, + num_macroblocks, mpeg12_macroblocks, fence); +} + +static void r300_mpeg12_clear_surface(struct pipe_video_context *vpipe, + unsigned x, unsigned y, + unsigned width, unsigned height, + unsigned value, + struct pipe_surface *surface) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + + assert(vpipe); + assert(surface); + + if (ctx->pipe->surface_fill) + ctx->pipe->surface_fill(ctx->pipe, surface, x, y, width, height, value); + else + util_surface_fill(ctx->pipe, surface, x, y, width, height, value); +} + +static void +r300_mpeg12_render_picture(struct pipe_video_context *vpipe, + struct pipe_video_surface *src_surface, + enum pipe_mpeg12_picture_type picture_type, + struct pipe_video_rect *src_area, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + + assert(vpipe); + assert(src_surface); + assert(src_area); + assert(dst_surface); + assert(dst_area); + + vl_compositor_render(&ctx->compositor, + r300_video_surface(src_surface)->tex, + picture_type, src_area, dst_surface->texture, + dst_area, fence); +} + +static void r300_mpeg12_set_decode_target(struct pipe_video_context *vpipe, + struct pipe_video_surface *dt) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + + assert(vpipe); + assert(dt); + + pipe_video_surface_reference(&ctx->decode_target, dt); +} + +static void r300_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, + const float *mat) +{ + struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe; + + assert(vpipe); + + vl_compositor_set_csc_matrix(&ctx->compositor, mat); +} + +static bool r300_mpeg12_init_pipe_state(struct radeon_mpeg12_context *ctx) +{ + struct pipe_rasterizer_state rast; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + unsigned i; + + assert(ctx); + + rast.flatshade = 1; + rast.flatshade_first = 0; + rast.light_twoside = 0; + rast.front_winding = PIPE_WINDING_CCW; + rast.cull_mode = PIPE_WINDING_CW; + rast.fill_cw = PIPE_POLYGON_MODE_FILL; + rast.fill_ccw = PIPE_POLYGON_MODE_FILL; + rast.offset_cw = 0; + rast.offset_ccw = 0; + rast.scissor = 0; + rast.poly_smooth = 0; + rast.poly_stipple_enable = 0; + rast.point_sprite = 0; + rast.point_size_per_vertex = 0; + rast.multisample = 0; + rast.line_smooth = 0; + rast.line_stipple_enable = 0; + rast.line_stipple_factor = 0; + rast.line_stipple_pattern = 0; + rast.line_last_pixel = 0; + rast.bypass_vs_clip_and_viewport = 0; + rast.line_width = 1; + rast.point_smooth = 0; + rast.point_size = 1; + rast.offset_units = 1; + rast.offset_scale = 1; + /*rast.sprite_coord_mode[i] = ;*/ + ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast); + ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast); + + blend.blend_enable = 0; + blend.rgb_func = PIPE_BLEND_ADD; + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_func = PIPE_BLEND_ADD; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + /* Needed to allow color writes to FB, even if blending disabled */ + blend.colormask = PIPE_MASK_RGBA; + blend.dither = 0; + ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend); + ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend); + + dsa.depth.enabled = 0; + dsa.depth.writemask = 0; + dsa.depth.func = PIPE_FUNC_ALWAYS; + for (i = 0; i < 2; ++i) + { + dsa.stencil[i].enabled = 0; + dsa.stencil[i].func = PIPE_FUNC_ALWAYS; + dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].ref_value = 0; + dsa.stencil[i].valuemask = 0; + dsa.stencil[i].writemask = 0; + } + dsa.alpha.enabled = 0; + dsa.alpha.func = PIPE_FUNC_ALWAYS; + dsa.alpha.ref_value = 0; + ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa); + ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa); + + return true; +} + +static struct pipe_video_context * +r300_mpeg12_context_create(struct pipe_screen *screen, + enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned int width, + unsigned int height) +{ + struct radeon_mpeg12_context *ctx; + ctx = CALLOC_STRUCT(radeon_mpeg12_context); + if (!ctx) + return NULL; + + ctx->base.profile = profile; + ctx->base.chroma_format = chroma_format; + ctx->base.width = width; + ctx->base.height = height; + ctx->base.screen = screen; + + ctx->base.destroy = radeon_mpeg12_destroy; + ctx->base.decode_macroblocks = radeon_mpeg12_decode_macroblocks; + ctx->base.clear_surface = radeon_mpeg12_clear_surface; + ctx->base.render_picture = radeon_mpeg12_render_picture; + ctx->base.set_decode_target = radeon_mpeg12_set_decode_target; + ctx->base.set_csc_matrix = radeon_mpeg12_set_csc_matrix; + + ctx->pipe = r300_create_context(screen,(struct r300_winsys*)screen->winsys); + if (!ctx->pipe) + { + FREE(ctx); + return NULL; + } + + if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe, + width, height, chroma_format, + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE, + true)) + { + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) + { + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + if (!radeon_mpeg12_init_pipe_state(ctx)) + { + vl_compositor_cleanup(&ctx->compositor); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + return &ctx->base; +} + +struct pipe_video_context * +r300_video_create(struct pipe_context *pipe, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + unsigned pvctx_id) +{ + struct pipe_video_context *vpipe; + struct radeon_vl_context *rvl_ctx; + + assert(p_screen); + assert(width && height); + + /* create radeon pipe_context */ + switch(u_reduce_video_profile(profile)) + { + case PIPE_VIDEO_CODEC_MPEG12: + vpipe = radeon_mpeg12_context_create(p_screen, profile, chr_f, + width, height); + break; + default: + return NULL; + } + + /* create radeon_vl_context */ + rvl_ctx = calloc(1, sizeof(struct radeon_vl_context)); + rvl_ctx->display = display; + rvl_ctx->screen = screen; + + vpipe->priv = rvl_ctx; + + return vpipe; +} diff --git a/src/gallium/drivers/r300/r300_video_context.h b/src/gallium/drivers/r300/r300_video_context.h new file mode 100644 index 00000000000..a8210ba7b71 --- /dev/null +++ b/src/gallium/drivers/r300/r300_video_context.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009-2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * CooperYuan <[email protected]>, <[email protected]> + */ + +#ifndef __R300_VIDEO_CONTEXT_H__ +#define __R300_VIDEO_CONTEXT_H__ + +#include <pipe/p_video_context.h> + +struct pipe_context; + +struct pipe_video_context* +r300_video_create(struct pipe_context *pipe, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + unsigned pvctx_id); + +#endif diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile index b476b9af3b8..a690b671e49 100644 --- a/src/gallium/drivers/r600/Makefile +++ b/src/gallium/drivers/r600/Makefile @@ -17,6 +17,7 @@ C_SOURCES = \ r600_shader.c \ r600_state.c \ r600_texture.c \ + r600_video_context.c \ r700_asm.c \ evergreen_state.c \ eg_asm.c \ diff --git a/src/gallium/drivers/r600/eg_asm.c b/src/gallium/drivers/r600/eg_asm.c index c44506c7eba..1881e633d54 100644 --- a/src/gallium/drivers/r600/eg_asm.c +++ b/src/gallium/drivers/r600/eg_asm.c @@ -32,10 +32,12 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) { unsigned id = cf->id; + unsigned end_of_program = bc->cf.prev == &cf->list; switch (cf->inst) { case (EG_V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3): case (EG_V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): + assert(!end_of_program); bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1) | S_SQ_CF_ALU_WORD0_KCACHE_MODE0(cf->kcache[0].mode) | S_SQ_CF_ALU_WORD0_KCACHE_BANK0(cf->kcache[0].bank) | @@ -44,15 +46,16 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) S_SQ_CF_ALU_WORD1_KCACHE_MODE1(cf->kcache[1].mode) | S_SQ_CF_ALU_WORD1_KCACHE_ADDR0(cf->kcache[0].addr) | S_SQ_CF_ALU_WORD1_KCACHE_ADDR1(cf->kcache[1].addr) | - S_SQ_CF_ALU_WORD1_BARRIER(1) | - S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1); + S_SQ_CF_ALU_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1); break; case EG_V_SQ_CF_WORD1_SQ_CF_INST_TEX: case EG_V_SQ_CF_WORD1_SQ_CF_INST_VTX: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1); + S_SQ_CF_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1) | + S_SQ_CF_WORD1_END_OF_PROGRAM(end_of_program); break; case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: @@ -60,13 +63,14 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(cf->output.elem_size) | S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(cf->output.array_base) | S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(cf->output.type); - bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) | + bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT(cf->output.burst_count - 1) | + S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(cf->output.swizzle_y) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(cf->output.swizzle_z) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(cf->output.swizzle_w) | - S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->output.barrier) | - S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->output.inst) | - S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(cf->output.end_of_program); + S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->inst) | + S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(end_of_program); break; case EG_V_SQ_CF_WORD1_SQ_CF_INST_JUMP: case EG_V_SQ_CF_WORD1_SQ_CF_INST_ELSE: @@ -79,9 +83,10 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) case EG_V_SQ_CF_WORD1_SQ_CF_INST_RETURN: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->cf_addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COND(cf->cond) | - S_SQ_CF_WORD1_POP_COUNT(cf->pop_count); + S_SQ_CF_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_WORD1_COND(cf->cond) | + S_SQ_CF_WORD1_POP_COUNT(cf->pop_count) | + S_SQ_CF_WORD1_END_OF_PROGRAM(end_of_program); break; default: diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c index 1c138513f6a..31f386964a1 100644 --- a/src/gallium/drivers/r600/r600_asm.c +++ b/src/gallium/drivers/r600/r600_asm.c @@ -32,6 +32,12 @@ #include "r600_formats.h" #include "r600d.h" +#define NUM_OF_CYCLES 3 +#define NUM_OF_COMPONENTS 4 + +#define PREV_ALU(alu) LIST_ENTRY(struct r600_bc_alu, alu->list.prev, list) +#define NEXT_ALU(alu) LIST_ENTRY(struct r600_bc_alu, alu->list.next, list) + static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) { if(alu->is_op3) @@ -45,10 +51,10 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE: - case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL: + case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN: - case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE: + case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE: @@ -61,7 +67,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE: return 2; - case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV: + case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR: @@ -76,7 +82,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS: return 1; default: R600_ERR( - "Need instruction operand number for 0x%x.\n", alu->inst); + "Need instruction operand number for 0x%x.\n", alu->inst); }; return 3; @@ -94,6 +100,7 @@ static struct r600_bc_cf *r600_bc_cf(void) LIST_INITHEAD(&cf->alu); LIST_INITHEAD(&cf->vtx); LIST_INITHEAD(&cf->tex); + cf->barrier = 1; return cf; } @@ -104,7 +111,6 @@ static struct r600_bc_alu *r600_bc_alu(void) if (alu == NULL) return NULL; LIST_INITHEAD(&alu->list); - LIST_INITHEAD(&alu->bs_list); return alu; } @@ -183,6 +189,44 @@ static int r600_bc_add_cf(struct r600_bc *bc) return 0; } +static void r600_bc_remove_cf(struct r600_bc *bc, struct r600_bc_cf *cf) +{ + struct r600_bc_cf *other; + LIST_FOR_EACH_ENTRY(other, &bc->cf, list) { + if (other->id > cf->id) + other->id -= 2; + if (other->cf_addr > cf->id) + other->cf_addr -= 2; + } + LIST_DEL(&cf->list); + free(cf); +} + +static void r600_bc_move_cf(struct r600_bc *bc, struct r600_bc_cf *cf, struct r600_bc_cf *next) +{ + struct r600_bc_cf *prev = LIST_ENTRY(struct r600_bc_cf, next->list.prev, list); + unsigned old_id = cf->id; + unsigned new_id = prev->id + 2; + struct r600_bc_cf *other; + + if (prev == cf) + return; /* position hasn't changed */ + + LIST_DEL(&cf->list); + LIST_FOR_EACH_ENTRY(other, &bc->cf, list) { + if (other->id > old_id) + other->id -= 2; + if (other->id >= new_id) + other->id += 2; + if (other->cf_addr > old_id) + other->cf_addr -= 2; + if (other->cf_addr > new_id) + other->cf_addr += 2; + } + cf->id = new_id; + LIST_ADD(&cf->list, &prev->list); +} + int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output) { int r; @@ -190,227 +234,620 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output) r = r600_bc_add_cf(bc); if (r) return r; - bc->cf_last->inst = output->inst; + bc->cf_last->inst = BC_INST(bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT); memcpy(&bc->cf_last->output, output, sizeof(struct r600_bc_output)); + bc->cf_last->output.burst_count = 1; return 0; } -const unsigned bank_swizzle_vec[8] = {SQ_ALU_VEC_210, //000 - SQ_ALU_VEC_120, //001 - SQ_ALU_VEC_102, //010 +/* alu predicate instructions */ +static int is_alu_pred_inst(struct r600_bc_alu *alu) +{ + return !alu->is_op3 && ( + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_INV || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_POP || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_CLR || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SET_RESTORE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_PUSH_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGT_PUSH_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETGE_PUSH_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_PUSH_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLT_PUSH_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETLE_PUSH_INT); +} - SQ_ALU_VEC_201, //011 - SQ_ALU_VEC_012, //100 - SQ_ALU_VEC_021, //101 +/* alu kill instructions */ +static int is_alu_kill_inst(struct r600_bc_alu *alu) +{ + return !alu->is_op3 && ( + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLNE_INT); +} - SQ_ALU_VEC_012, //110 - SQ_ALU_VEC_012}; //111 +/* alu instructions that can ony exits once per group */ +static int is_alu_once_inst(struct r600_bc_alu *alu) +{ + return is_alu_kill_inst(alu) || + is_alu_pred_inst(alu); +} -const unsigned bank_swizzle_scl[8] = {SQ_ALU_SCL_210, //000 - SQ_ALU_SCL_122, //001 - SQ_ALU_SCL_122, //010 +static int is_alu_reduction_inst(struct r600_bc_alu *alu) +{ + return !alu->is_op3 && ( + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4 || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4_IEEE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX4); +} + +static int is_alu_mova_inst(struct r600_bc_alu *alu) +{ + return !alu->is_op3 && ( + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT); +} + +/* alu instructions that can only execute on the vector unit */ +static int is_alu_vec_unit_inst(struct r600_bc_alu *alu) +{ + return is_alu_reduction_inst(alu) || + is_alu_mova_inst(alu); +} + +/* alu instructions that can only execute on the trans unit */ +static int is_alu_trans_unit_inst(struct r600_bc_alu *alu) +{ + if(!alu->is_op3) + return alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ASHR_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHL_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULHI_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_INT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_UINT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_UINT_TO_FLT || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_CLAMPED || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_FF || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_CLAMPED || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_FF || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_IEEE || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN || + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SQRT_IEEE; + else + return alu->inst == V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT || + alu->inst == V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_D2 || + alu->inst == V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M2 || + alu->inst == V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT_M4; +} + +/* alu instructions that can execute on any unit */ +static int is_alu_any_unit_inst(struct r600_bc_alu *alu) +{ + return !is_alu_vec_unit_inst(alu) && + !is_alu_trans_unit_inst(alu); +} + +static int assign_alu_units(struct r600_bc_alu *alu_first, struct r600_bc_alu *assignment[5]) +{ + struct r600_bc_alu *alu; + unsigned i, chan, trans; + + for (i = 0; i < 5; i++) + assignment[i] = NULL; + + for (alu = alu_first; alu; alu = NEXT_ALU(alu)) { + chan = alu->dst.chan; + if (is_alu_trans_unit_inst(alu)) + trans = 1; + else if (is_alu_vec_unit_inst(alu)) + trans = 0; + else if (assignment[chan]) + trans = 1; // assume ALU_INST_PREFER_VECTOR + else + trans = 0; - SQ_ALU_SCL_221, //011 - SQ_ALU_SCL_212, //100 - SQ_ALU_SCL_122, //101 + if (trans) { + if (assignment[4]) { + assert(0); //ALU.Trans has already been allocated + return -1; + } + assignment[4] = alu; + } else { + if (assignment[chan]) { + assert(0); //ALU.chan has already been allocated + return -1; + } + assignment[chan] = alu; + } - SQ_ALU_SCL_122, //110 - SQ_ALU_SCL_122}; //111 + if (alu->last) + break; + } + return 0; +} -static int init_gpr(struct r600_bc_alu *alu) +struct alu_bank_swizzle { + int hw_gpr[NUM_OF_CYCLES][NUM_OF_COMPONENTS]; + int hw_cfile_addr[4]; + int hw_cfile_elem[4]; +}; + +const unsigned cycle_for_bank_swizzle_vec[][3] = { + [SQ_ALU_VEC_012] = { 0, 1, 2 }, + [SQ_ALU_VEC_021] = { 0, 2, 1 }, + [SQ_ALU_VEC_120] = { 1, 2, 0 }, + [SQ_ALU_VEC_102] = { 1, 0, 2 }, + [SQ_ALU_VEC_201] = { 2, 0, 1 }, + [SQ_ALU_VEC_210] = { 2, 1, 0 } +}; + +const unsigned cycle_for_bank_swizzle_scl[][3] = { + [SQ_ALU_SCL_210] = { 2, 1, 0 }, + [SQ_ALU_SCL_122] = { 1, 2, 2 }, + [SQ_ALU_SCL_212] = { 2, 1, 2 }, + [SQ_ALU_SCL_221] = { 2, 2, 1 } +}; + +static void init_bank_swizzle(struct alu_bank_swizzle *bs) { - int cycle, component; + int i, cycle, component; /* set up gpr use */ for (cycle = 0; cycle < NUM_OF_CYCLES; cycle++) for (component = 0; component < NUM_OF_COMPONENTS; component++) - alu->hw_gpr[cycle][component] = -1; - return 0; + bs->hw_gpr[cycle][component] = -1; + for (i = 0; i < 4; i++) + bs->hw_cfile_addr[i] = -1; + for (i = 0; i < 4; i++) + bs->hw_cfile_elem[i] = -1; } -#if 0 -static int reserve_gpr(struct r600_bc_alu *alu, unsigned sel, unsigned chan, unsigned cycle) +static int reserve_gpr(struct alu_bank_swizzle *bs, unsigned sel, unsigned chan, unsigned cycle) { - if (alu->hw_gpr[cycle][chan] < 0) - alu->hw_gpr[cycle][chan] = sel; - else if (alu->hw_gpr[cycle][chan] != (int)sel) { - R600_ERR("Another scalar operation has already used GPR read port for channel\n"); + if (bs->hw_gpr[cycle][chan] == -1) + bs->hw_gpr[cycle][chan] = sel; + else if (bs->hw_gpr[cycle][chan] != (int)sel) { + // Another scalar operation has already used GPR read port for channel return -1; } return 0; } -static int cycle_for_scalar_bank_swizzle(const int swiz, const int sel, unsigned *p_cycle) -{ - int table[3]; - int ret = 0; - switch (swiz) { - case SQ_ALU_SCL_210: - table[0] = 2; table[1] = 1; table[2] = 0; - *p_cycle = table[sel]; - break; - case SQ_ALU_SCL_122: - table[0] = 1; table[1] = 2; table[2] = 2; - *p_cycle = table[sel]; - break; - case SQ_ALU_SCL_212: - table[0] = 2; table[1] = 1; table[2] = 2; - *p_cycle = table[sel]; - break; - case SQ_ALU_SCL_221: - table[0] = 2; table[1] = 2; table[2] = 1; - *p_cycle = table[sel]; - break; - break; - default: - R600_ERR("bad scalar bank swizzle value\n"); - ret = -1; - break; +static int reserve_cfile(struct alu_bank_swizzle *bs, unsigned sel, unsigned chan) +{ + int res, resmatch = -1, resempty = -1; + for (res = 3; res >= 0; --res) { + if (bs->hw_cfile_addr[res] == -1) + resempty = res; + else if (bs->hw_cfile_addr[res] == sel && + bs->hw_cfile_elem[res] == chan) + resmatch = res; } - return ret; -} - -static int cycle_for_vector_bank_swizzle(const int swiz, const int sel, unsigned *p_cycle) -{ - int table[3]; - int ret; - - switch (swiz) { - case SQ_ALU_VEC_012: - table[0] = 0; table[1] = 1; table[2] = 2; - *p_cycle = table[sel]; - break; - case SQ_ALU_VEC_021: - table[0] = 0; table[1] = 2; table[2] = 1; - *p_cycle = table[sel]; - break; - case SQ_ALU_VEC_120: - table[0] = 1; table[1] = 2; table[2] = 0; - *p_cycle = table[sel]; - break; - case SQ_ALU_VEC_102: - table[0] = 1; table[1] = 0; table[2] = 2; - *p_cycle = table[sel]; - break; - case SQ_ALU_VEC_201: - table[0] = 2; table[1] = 0; table[2] = 1; - *p_cycle = table[sel]; - break; - case SQ_ALU_VEC_210: - table[0] = 2; table[1] = 1; table[2] = 0; - *p_cycle = table[sel]; - break; - default: - R600_ERR("bad vector bank swizzle value\n"); - ret = -1; - break; + if (resmatch != -1) + return 0; // Read for this scalar element already reserved, nothing to do here. + else if (resempty != -1) { + bs->hw_cfile_addr[resempty] = sel; + bs->hw_cfile_elem[resempty] = chan; + } else { + // All cfile read ports are used, cannot reference vector element + return -1; } - return ret; + return 0; } +static int is_gpr(unsigned sel) +{ + return (sel >= 0 && sel <= 127); +} +static int is_cfile(unsigned sel) +{ + return (sel > 255 && sel < 512); +} -static void update_chan_counter(struct r600_bc_alu *alu, int *chan_counter) +/* CB constants start at 512, and get translated to a kcache index when ALU + * clauses are constructed. Note that we handle kcache constants the same way + * as (the now gone) cfile constants, is that really required? */ +static int is_cb_const(int sel) { - int num_src; - int i; - int channel_swizzle; + if (sel > 511 && sel < 4607) + return 1; + return 0; +} - num_src = r600_bc_get_num_operands(alu); +static int is_const(int sel) +{ + return is_cfile(sel) || + is_cb_const(sel) || + (sel >= V_SQ_ALU_SRC_0 && + sel <= V_SQ_ALU_SRC_LITERAL); +} + +static int check_vector(struct r600_bc_alu *alu, struct alu_bank_swizzle *bs, int bank_swizzle) +{ + int r, src, num_src, sel, elem, cycle; - for (i = 0; i < num_src; i++) { - channel_swizzle = alu->src[i].chan; - if ((alu->src[i].sel > 0 && alu->src[i].sel < 128) && channel_swizzle <= 3) - chan_counter[channel_swizzle]++; + num_src = r600_bc_get_num_operands(alu); + for (src = 0; src < num_src; src++) { + sel = alu->src[src].sel; + elem = alu->src[src].chan; + if (is_gpr(sel)) { + cycle = cycle_for_bank_swizzle_vec[bank_swizzle][src]; + if (src == 1 && sel == alu->src[0].sel && elem == alu->src[0].chan) + // Nothing to do; special-case optimization, + // second source uses first source’s reservation + continue; + else { + r = reserve_gpr(bs, sel, elem, cycle); + if (r) + return r; + } + } else if (is_cfile(sel)) { + r = reserve_cfile(bs, sel, elem); + if (r) + return r; + } + // No restrictions on PV, PS, literal or special constants } + return 0; } -/* we need something like this I think - but this is bogus */ -int check_read_slots(struct r600_bc *bc, struct r600_bc_alu *alu_first) +static int check_scalar(struct r600_bc_alu *alu, struct alu_bank_swizzle *bs, int bank_swizzle) { - struct r600_bc_alu *alu; - int chan_counter[4] = { 0 }; - - update_chan_counter(alu_first, chan_counter); + int r, src, num_src, const_count, sel, elem, cycle; - LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) { - update_chan_counter(alu, chan_counter); + num_src = r600_bc_get_num_operands(alu); + for (const_count = 0, src = 0; src < num_src; ++src) { + sel = alu->src[src].sel; + elem = alu->src[src].chan; + if (is_const(sel)) { // Any constant, including literal and inline constants + if (const_count >= 2) + // More than two references to a constant in + // transcendental operation. + return -1; + else + const_count++; + } + if (is_cfile(sel)) { + r = reserve_cfile(bs, sel, elem); + if (r) + return r; + } } - - if (chan_counter[0] > 3 || - chan_counter[1] > 3 || - chan_counter[2] > 3 || - chan_counter[3] > 3) { - R600_ERR("needed to split instruction for input ran out of banks %x %d %d %d %d\n", - alu_first->inst, chan_counter[0], chan_counter[1], chan_counter[2], chan_counter[3]); - return -1; + for (src = 0; src < num_src; ++src) { + sel = alu->src[src].sel; + elem = alu->src[src].chan; + if (is_gpr(sel)) { + cycle = cycle_for_bank_swizzle_scl[bank_swizzle][src]; + if (cycle < const_count) + // Cycle for GPR load conflicts with + // constant load in transcendental operation. + return -1; + r = reserve_gpr(bs, sel, elem, cycle); + if (r) + return r; + } + // Constants already processed + // No restrictions on PV, PS } return 0; } -#endif -/* CB constants start at 512, and get translated to a kcache index when ALU - * clauses are constructed. Note that we handle kcache constants the same way - * as (the now gone) cfile constants, is that really required? */ -static int is_const(int sel) +static int check_and_set_bank_swizzle(struct r600_bc_alu *slots[5]) { - if (sel > 511 && sel < 4607) - return 1; - return 0; + struct alu_bank_swizzle bs; + int bank_swizzle[5]; + int i, r = 0, forced = 0; + + for (i = 0; i < 5; i++) + if (slots[i] && slots[i]->bank_swizzle_force) { + slots[i]->bank_swizzle = slots[i]->bank_swizzle_force; + forced = 1; + } + + if (forced) + return 0; + + // just check every possible combination of bank swizzle + // not very efficent, but works on the first try in most of the cases + for (i = 0; i < 4; i++) + bank_swizzle[i] = SQ_ALU_VEC_012; + bank_swizzle[4] = SQ_ALU_SCL_210; + while(bank_swizzle[4] <= SQ_ALU_SCL_221) { + init_bank_swizzle(&bs); + for (i = 0; i < 4; i++) { + if (slots[i]) { + r = check_vector(slots[i], &bs, bank_swizzle[i]); + if (r) + break; + } + } + if (!r && slots[4]) { + r = check_scalar(slots[4], &bs, bank_swizzle[4]); + } + if (!r) { + for (i = 0; i < 5; i++) { + if (slots[i]) + slots[i]->bank_swizzle = bank_swizzle[i]; + } + return 0; + } + + for (i = 0; i < 5; i++) { + bank_swizzle[i]++; + if (bank_swizzle[i] <= SQ_ALU_VEC_210) + break; + else + bank_swizzle[i] = SQ_ALU_VEC_012; + } + } + + // couldn't find a working swizzle + return -1; } -static int check_scalar(struct r600_bc *bc, struct r600_bc_alu *alu) +static int replace_gpr_with_pv_ps(struct r600_bc_alu *slots[5], struct r600_bc_alu *alu_prev) { - unsigned swizzle_key; + struct r600_bc_alu *prev[5]; + int gpr[5], chan[5]; + int i, j, r, src, num_src; - if (alu->bank_swizzle_force) { - alu->bank_swizzle = alu->bank_swizzle_force; - return 0; + r = assign_alu_units(alu_prev, prev); + if (r) + return r; + + for (i = 0; i < 5; ++i) { + if(prev[i] && prev[i]->dst.write && !prev[i]->dst.rel) { + gpr[i] = prev[i]->dst.sel; + if (is_alu_reduction_inst(prev[i])) + chan[i] = 0; + else + chan[i] = prev[i]->dst.chan; + } else + gpr[i] = -1; + } + + for (i = 0; i < 5; ++i) { + struct r600_bc_alu *alu = slots[i]; + if(!alu) + continue; + + num_src = r600_bc_get_num_operands(alu); + for (src = 0; src < num_src; ++src) { + if (!is_gpr(alu->src[src].sel) || alu->src[src].rel) + continue; + + if (alu->src[src].sel == gpr[4] && + alu->src[src].chan == chan[4]) { + alu->src[src].sel = V_SQ_ALU_SRC_PS; + alu->src[src].chan = 0; + continue; + } + + for (j = 0; j < 4; ++j) { + if (alu->src[src].sel == gpr[j] && + alu->src[src].chan == j) { + alu->src[src].sel = V_SQ_ALU_SRC_PV; + alu->src[src].chan = chan[j]; + break; + } + } + } } - swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) + - (is_const(alu->src[1].sel) ? 2 : 0 ) + - (is_const(alu->src[2].sel) ? 1 : 0 ); - alu->bank_swizzle = bank_swizzle_scl[swizzle_key]; return 0; } -static int check_vector(struct r600_bc *bc, struct r600_bc_alu *alu) +void r600_bc_special_constants(u32 value, unsigned *sel, unsigned *neg) { - unsigned swizzle_key; - - if (alu->bank_swizzle_force) { - alu->bank_swizzle = alu->bank_swizzle_force; - return 0; + switch(value) { + case 0: + *sel = V_SQ_ALU_SRC_0; + break; + case 1: + *sel = V_SQ_ALU_SRC_1_INT; + break; + case -1: + *sel = V_SQ_ALU_SRC_M_1_INT; + break; + case 0x3F800000: // 1.0f + *sel = V_SQ_ALU_SRC_1; + break; + case 0x3F000000: // 0.5f + *sel = V_SQ_ALU_SRC_0_5; + break; + case 0xBF800000: // -1.0f + *sel = V_SQ_ALU_SRC_1; + *neg ^= 1; + break; + case 0xBF000000: // -0.5f + *sel = V_SQ_ALU_SRC_0_5; + *neg ^= 1; + break; + default: + *sel = V_SQ_ALU_SRC_LITERAL; + break; } - swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) + - (is_const(alu->src[1].sel) ? 2 : 0 ) + - (is_const(alu->src[2].sel) ? 1 : 0 ); +} - alu->bank_swizzle = bank_swizzle_vec[swizzle_key]; +/* compute how many literal are needed */ +static int r600_bc_alu_nliterals(struct r600_bc_alu *alu, uint32_t literal[4], unsigned *nliteral) +{ + unsigned num_src = r600_bc_get_num_operands(alu); + unsigned i, j; + + for (i = 0; i < num_src; ++i) { + if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) { + uint32_t value = alu->src[i].value[alu->src[i].chan]; + unsigned found = 0; + for (j = 0; j < *nliteral; ++j) { + if (literal[j] == value) { + found = 1; + break; + } + } + if (!found) { + if (*nliteral >= 4) + return -EINVAL; + literal[(*nliteral)++] = value; + } + } + } return 0; } -static int check_and_set_bank_swizzle(struct r600_bc *bc, struct r600_bc_alu *alu_first) +static void r600_bc_alu_adjust_literals(struct r600_bc_alu *alu, uint32_t literal[4], unsigned nliteral) { - struct r600_bc_alu *alu = NULL; - int num_instr = 1; + unsigned num_src = r600_bc_get_num_operands(alu); + unsigned i, j; + + for (i = 0; i < num_src; ++i) { + if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) { + uint32_t value = alu->src[i].value[alu->src[i].chan]; + for (j = 0; j < nliteral; ++j) { + if (literal[j] == value) { + alu->src[i].chan = j; + break; + } + } + } + } +} - init_gpr(alu_first); +static int merge_inst_groups(struct r600_bc *bc, struct r600_bc_alu *slots[5], struct r600_bc_alu *alu_prev) +{ + struct r600_bc_alu *prev[5]; + struct r600_bc_alu *result[5] = { NULL }; + + uint32_t literal[4]; + unsigned nliteral = 0; + + int i, j, r, src, num_src; + int num_once_inst = 0; + + r = assign_alu_units(alu_prev, prev); + if (r) + return r; - LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) { - num_instr++; + for (i = 0; i < 5; ++i) { + /* check number of literals */ + if (prev[i] && r600_bc_alu_nliterals(prev[i], literal, &nliteral)) + return 0; + if (slots[i] && r600_bc_alu_nliterals(slots[i], literal, &nliteral)) + return 0; + + // let's check used slots + if (prev[i] && !slots[i]) { + result[i] = prev[i]; + num_once_inst += is_alu_once_inst(prev[i]); + continue; + } else if (prev[i] && slots[i]) { + if (result[4] == NULL && prev[4] == NULL && slots[4] == NULL) { + // trans unit is still free try to use it + if (is_alu_any_unit_inst(slots[i])) { + result[i] = prev[i]; + result[4] = slots[i]; + } else if (is_alu_any_unit_inst(prev[i])) { + result[i] = slots[i]; + result[4] = prev[i]; + } else + return 0; + } else + return 0; + } else if(!slots[i]) { + continue; + } else + result[i] = slots[i]; + + // let's check source gprs + struct r600_bc_alu *alu = slots[i]; + num_once_inst += is_alu_once_inst(alu); + + num_src = r600_bc_get_num_operands(alu); + for (src = 0; src < num_src; ++src) { + // constants doesn't matter + if (!is_gpr(alu->src[src].sel)) + continue; + + for (j = 0; j < 5; ++j) { + if (!prev[j] || !prev[j]->dst.write) + continue; + + // if it's relative then we can't determin which gpr is really used + if (prev[j]->dst.chan == alu->src[src].chan && + (prev[j]->dst.sel == alu->src[src].sel || + prev[j]->dst.rel || alu->src[src].rel)) + return 0; + } + } } - if (num_instr == 1) { - check_scalar(bc, alu_first); - - } else { -/* check_read_slots(bc, bc->cf_last->curr_bs_head);*/ - check_vector(bc, alu_first); - LIST_FOR_EACH_ENTRY(alu, &alu_first->bs_list, bs_list) { - check_vector(bc, alu); + /* more than one PRED_ or KILL_ ? */ + if (num_once_inst > 1) + return 0; + + /* check if the result can still be swizzlet */ + r = check_and_set_bank_swizzle(result); + if (r) + return 0; + + /* looks like everything worked out right, apply the changes */ + + /* sort instructions */ + for (i = 0; i < 5; ++i) { + slots[i] = result[i]; + if (result[i]) { + LIST_DEL(&result[i]->list); + result[i]->last = 0; + LIST_ADDTAIL(&result[i]->list, &bc->cf_last->alu); } } + + /* determine new last instruction */ + LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list)->last = 1; + + /* determine new first instruction */ + for (i = 0; i < 5; ++i) { + if (result[i]) { + bc->cf_last->curr_bs_head = result[i]; + break; + } + } + + bc->cf_last->prev_bs_head = bc->cf_last->prev2_bs_head; + bc->cf_last->prev2_bs_head = NULL; + return 0; } @@ -537,18 +974,30 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int if (nalu == NULL) return -ENOMEM; memcpy(nalu, alu, sizeof(struct r600_bc_alu)); - nalu->nliteral = 0; + + if (bc->cf_last != NULL && bc->cf_last->inst != (type << 3)) { + /* check if we could add it anyway */ + if (bc->cf_last->inst == (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3) && + type == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE) { + LIST_FOR_EACH_ENTRY(lalu, &bc->cf_last->alu, list) { + if (lalu->predicate) { + bc->force_add_cf = 1; + break; + } + } + } else + bc->force_add_cf = 1; + } /* cf can contains only alu or only vtx or only tex */ - if (bc->cf_last == NULL || bc->cf_last->inst != (type << 3) || - bc->force_add_cf) { + if (bc->cf_last == NULL || bc->force_add_cf) { r = r600_bc_add_cf(bc); if (r) { free(nalu); return r; } - bc->cf_last->inst = (type << 3); } + bc->cf_last->inst = (type << 3); /* Setup the kcache for this ALU instruction. This will start a new * ALU clause if needed. */ @@ -559,38 +1008,27 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int if (!bc->cf_last->curr_bs_head) { bc->cf_last->curr_bs_head = nalu; - LIST_INITHEAD(&nalu->bs_list); - } else { - LIST_ADDTAIL(&nalu->bs_list, &bc->cf_last->curr_bs_head->bs_list); } - /* at most 128 slots, one add alu can add 4 slots + 4 constants(2 slots) + /* at most 128 slots, one add alu can add 5 slots + 4 constants(2 slots) * worst case */ if (nalu->last && (bc->cf_last->ndw >> 1) >= 120) { bc->force_add_cf = 1; } - /* number of gpr == the last gpr used in any alu */ + /* replace special constants */ for (i = 0; i < 3; i++) { + if (nalu->src[i].sel == V_SQ_ALU_SRC_LITERAL) + r600_bc_special_constants( + nalu->src[i].value[nalu->src[i].chan], + &nalu->src[i].sel, &nalu->src[i].neg); + if (nalu->src[i].sel >= bc->ngpr && nalu->src[i].sel < 128) { bc->ngpr = nalu->src[i].sel + 1; } - /* compute how many literal are needed - * either 2 or 4 literals - */ - if (nalu->src[i].sel == 253) { - if (((nalu->src[i].chan + 2) & 0x6) > nalu->nliteral) { - nalu->nliteral = (nalu->src[i].chan + 2) & 0x6; - } - } - } - if (!LIST_IS_EMPTY(&bc->cf_last->alu)) { - lalu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list); - if (!lalu->last && lalu->nliteral > nalu->nliteral) { - nalu->nliteral = lalu->nliteral; - } } if (nalu->dst.sel >= bc->ngpr) { bc->ngpr = nalu->dst.sel + 1; } + LIST_ADDTAIL(&nalu->list, &bc->cf_last->alu); /* each alu use 2 dwords */ bc->cf_last->ndw += 2; @@ -598,7 +1036,29 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int /* process cur ALU instructions for bank swizzle */ if (nalu->last) { - check_and_set_bank_swizzle(bc, bc->cf_last->curr_bs_head); + struct r600_bc_alu *slots[5]; + r = assign_alu_units(bc->cf_last->curr_bs_head, slots); + if (r) + return r; + + if (bc->cf_last->prev_bs_head) { + r = merge_inst_groups(bc, slots, bc->cf_last->prev_bs_head); + if (r) + return r; + } + + if (bc->cf_last->prev_bs_head) { + r = replace_gpr_with_pv_ps(slots, bc->cf_last->prev_bs_head); + if (r) + return r; + } + + r = check_and_set_bank_swizzle(slots); + if (r) + return r; + + bc->cf_last->prev2_bs_head = bc->cf_last->prev_bs_head; + bc->cf_last->prev_bs_head = bc->cf_last->curr_bs_head; bc->cf_last->curr_bs_head = NULL; } return 0; @@ -609,42 +1069,14 @@ int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu) return r600_bc_add_alu_type(bc, alu, BC_INST(bc, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU)); } -int r600_bc_add_literal(struct r600_bc *bc, const u32 *value) +static void r600_bc_remove_alu(struct r600_bc_cf *cf, struct r600_bc_alu *alu) { - struct r600_bc_alu *alu; - - if (bc->cf_last == NULL) { - return 0; - } - if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_TEX) { - return 0; - } - /* all same on EG */ - if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_JUMP || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_ELSE || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END || - bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_POP) { - return 0; - } - /* same on EG */ - if (((bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3)) && - (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3))) || - LIST_IS_EMPTY(&bc->cf_last->alu)) { - R600_ERR("last CF is not ALU (%p)\n", bc->cf_last); - return -EINVAL; - } - alu = LIST_ENTRY(struct r600_bc_alu, bc->cf_last->alu.prev, list); - if (!alu->last || !alu->nliteral || alu->literal_added) { - return 0; + if (alu->last && alu->list.prev != &cf->alu) { + PREV_ALU(alu)->last = 1; } - memcpy(alu->value, value, 4 * 4); - bc->cf_last->ndw += alu->nliteral; - bc->ndw += alu->nliteral; - alu->literal_added = 1; - return 0; + LIST_DEL(&alu->list); + free(alu); + cf->ndw -= 2; } int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx) @@ -797,8 +1229,6 @@ static int r600_bc_tex_build(struct r600_bc *bc, struct r600_bc_tex *tex, unsign /* r600 only, r700/eg bits in r700_asm.c */ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id) { - unsigned i; - /* don't replace gpr by pv or ps for destination register */ bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) | S_SQ_ALU_WORD0_SRC0_REL(alu->src[0].rel) | @@ -829,30 +1259,70 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) | S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) | S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) | + S_SQ_ALU_WORD1_OP2_OMOD(alu->omod) | S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) | S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle) | S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) | S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate); } - if (alu->last) { - if (alu->nliteral && !alu->literal_added) { - R600_ERR("Bug in ALU processing for instruction 0x%08x, literal not added correctly\n", alu->inst); - } - for (i = 0; i < alu->nliteral; i++) { - bc->bytecode[id++] = alu->value[i]; - } - } return 0; } +enum cf_class +{ + CF_CLASS_ALU, + CF_CLASS_TEXTURE, + CF_CLASS_VERTEX, + CF_CLASS_EXPORT, + CF_CLASS_OTHER +}; + +static enum cf_class get_cf_class(struct r600_bc_cf *cf) +{ + switch (cf->inst) { + case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3): + case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3): + case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3): + case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): + return CF_CLASS_ALU; + + case V_SQ_CF_WORD1_SQ_CF_INST_TEX: + return CF_CLASS_TEXTURE; + + case V_SQ_CF_WORD1_SQ_CF_INST_VTX: + case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC: + return CF_CLASS_VERTEX; + + case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: + case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: + return CF_CLASS_EXPORT; + + case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: + case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: + case V_SQ_CF_WORD1_SQ_CF_INST_POP: + case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL: + case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: + case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: + case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: + case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: + return CF_CLASS_OTHER; + + default: + R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst); + return -EINVAL; + } +} + /* common for r600/r700 - eg in eg_asm.c */ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) { unsigned id = cf->id; + unsigned end_of_program = bc->cf.prev == &cf->list; - switch (cf->inst) { - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3): - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + assert(!end_of_program); bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1) | S_SQ_CF_ALU_WORD0_KCACHE_MODE0(cf->kcache[0].mode) | S_SQ_CF_ALU_WORD0_KCACHE_BANK0(cf->kcache[0].bank) | @@ -862,46 +1332,39 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) S_SQ_CF_ALU_WORD1_KCACHE_MODE1(cf->kcache[1].mode) | S_SQ_CF_ALU_WORD1_KCACHE_ADDR0(cf->kcache[0].addr) | S_SQ_CF_ALU_WORD1_KCACHE_ADDR1(cf->kcache[1].addr) | - S_SQ_CF_ALU_WORD1_BARRIER(1) | - S_SQ_CF_ALU_WORD1_USES_WATERFALL(bc->chiprev == CHIPREV_R600 ? cf->r6xx_uses_waterfall : 0) | - S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1); + S_SQ_CF_ALU_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_ALU_WORD1_USES_WATERFALL(bc->chiprev == CHIPREV_R600 ? cf->r6xx_uses_waterfall : 0) | + S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1); break; - case V_SQ_CF_WORD1_SQ_CF_INST_TEX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC: + case CF_CLASS_TEXTURE: + case CF_CLASS_VERTEX: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1); + S_SQ_CF_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_WORD1_COUNT((cf->ndw / 4) - 1) | + S_SQ_CF_WORD1_END_OF_PROGRAM(end_of_program); break; - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: + case CF_CLASS_EXPORT: bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(cf->output.gpr) | S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(cf->output.elem_size) | S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(cf->output.array_base) | S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(cf->output.type); - bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) | + bc->bytecode[id++] = S_SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT(cf->output.burst_count - 1) | + S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(cf->output.swizzle_x) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(cf->output.swizzle_y) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(cf->output.swizzle_z) | S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(cf->output.swizzle_w) | - S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->output.barrier) | - S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->output.inst) | - S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(cf->output.end_of_program); + S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(cf->inst) | + S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(end_of_program); break; - case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: - case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: - case V_SQ_CF_WORD1_SQ_CF_INST_POP: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: - case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: - case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: + case CF_CLASS_OTHER: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->cf_addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COND(cf->cond) | - S_SQ_CF_WORD1_POP_COUNT(cf->pop_count); + S_SQ_CF_WORD1_BARRIER(cf->barrier) | + S_SQ_CF_WORD1_COND(cf->cond) | + S_SQ_CF_WORD1_POP_COUNT(cf->pop_count) | + S_SQ_CF_WORD1_END_OF_PROGRAM(end_of_program); break; default: @@ -911,14 +1374,776 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) return 0; } +struct gpr_usage_range { + int replacement; + int32_t start; + int32_t end; +}; + +struct gpr_usage { + unsigned channels:4; + int32_t first_write; + int32_t last_write[4]; + unsigned nranges; + struct gpr_usage_range *ranges; +}; + +static struct gpr_usage_range* add_gpr_usage_range(struct gpr_usage *usage) +{ + usage->nranges++; + usage->ranges = realloc(usage->ranges, usage->nranges * sizeof(struct gpr_usage_range)); + if (!usage->ranges) + return NULL; + return &usage->ranges[usage->nranges-1]; +} + +static void notice_gpr_read(struct gpr_usage *usage, int32_t id, unsigned chan) +{ + usage->channels |= 1 << chan; + usage->first_write = -1; + if (!usage->nranges) { + struct gpr_usage_range* range = add_gpr_usage_range(usage); + range->replacement = -1; + range->start = -1; + range->end = -1; + } + if (usage->ranges[usage->nranges-1].end < id) + usage->ranges[usage->nranges-1].end = id; +} + +static void notice_gpr_rel_read(struct gpr_usage usage[128], int32_t id, unsigned chan) +{ + unsigned i; + for (i = 0; i < 128; ++i) + notice_gpr_read(&usage[i], id, chan); +} + +static void notice_gpr_last_write(struct gpr_usage *usage, int32_t id, unsigned chan) +{ + usage->last_write[chan] = id; +} + +static void notice_gpr_write(struct gpr_usage *usage, int32_t id, unsigned chan, + int predicate, int prefered_replacement) +{ + int32_t start = usage->first_write != -1 ? usage->first_write : id; + usage->channels &= ~(1 << chan); + if (usage->channels) { + if (usage->first_write == -1) + usage->first_write = id; + } else if (!usage->nranges || (usage->ranges[usage->nranges-1].start != start && !predicate)) { + usage->first_write = start; + struct gpr_usage_range* range = add_gpr_usage_range(usage); + range->replacement = prefered_replacement; + range->start = start; + range->end = -1; + } else if (usage->ranges[usage->nranges-1].start == start && prefered_replacement != -1) { + usage->ranges[usage->nranges-1].replacement = prefered_replacement; + } + notice_gpr_last_write(usage, id, chan); +} + +static void notice_gpr_rel_last_write(struct gpr_usage usage[128], int32_t id, unsigned chan) +{ + unsigned i; + for (i = 0; i < 128; ++i) + notice_gpr_last_write(&usage[i], id, chan); +} + +static void notice_gpr_rel_write(struct gpr_usage usage[128], int32_t id, unsigned chan) +{ + unsigned i; + for (i = 0; i < 128; ++i) + notice_gpr_write(&usage[i], id, chan, 1, -1); +} + +static void notice_alu_src_gprs(struct r600_bc_alu *alu, struct gpr_usage usage[128], int32_t id) +{ + unsigned src, num_src; + + num_src = r600_bc_get_num_operands(alu); + for (src = 0; src < num_src; ++src) { + // constants doesn't matter + if (!is_gpr(alu->src[src].sel)) + continue; + + if (alu->src[src].rel) + notice_gpr_rel_read(usage, id, alu->src[src].chan); + else + notice_gpr_read(&usage[alu->src[src].sel], id, alu->src[src].chan); + } +} + +static void notice_alu_dst_gprs(struct r600_bc_alu *alu_first, struct gpr_usage usage[128], + int32_t id, int predicate) +{ + struct r600_bc_alu *alu; + for (alu = alu_first; alu; alu = LIST_ENTRY(struct r600_bc_alu, alu->list.next, list)) { + if (alu->dst.write) { + if (alu->dst.rel) + notice_gpr_rel_write(usage, id, alu->dst.chan); + else if (alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV && is_gpr(alu->src[0].sel)) + notice_gpr_write(&usage[alu->dst.sel], id, alu->dst.chan, + predicate, alu->src[0].sel); + else + notice_gpr_write(&usage[alu->dst.sel], id, alu->dst.chan, predicate, -1); + } + + if (alu->last) + break; + } +} + +static void notice_tex_gprs(struct r600_bc_tex *tex, struct gpr_usage usage[128], + int32_t id, int predicate) +{ + if (tex->src_rel) { + if (tex->src_sel_x < 4) + notice_gpr_rel_read(usage, id, tex->src_sel_x); + if (tex->src_sel_y < 4) + notice_gpr_rel_read(usage, id, tex->src_sel_y); + if (tex->src_sel_z < 4) + notice_gpr_rel_read(usage, id, tex->src_sel_z); + if (tex->src_sel_w < 4) + notice_gpr_rel_read(usage, id, tex->src_sel_w); + } else { + if (tex->src_sel_x < 4) + notice_gpr_read(&usage[tex->src_gpr], id, tex->src_sel_x); + if (tex->src_sel_y < 4) + notice_gpr_read(&usage[tex->src_gpr], id, tex->src_sel_y); + if (tex->src_sel_z < 4) + notice_gpr_read(&usage[tex->src_gpr], id, tex->src_sel_z); + if (tex->src_sel_w < 4) + notice_gpr_read(&usage[tex->src_gpr], id, tex->src_sel_w); + } + if (tex->dst_rel) { + if (tex->dst_sel_x != 7) + notice_gpr_rel_write(usage, id, 0); + if (tex->dst_sel_y != 7) + notice_gpr_rel_write(usage, id, 1); + if (tex->dst_sel_z != 7) + notice_gpr_rel_write(usage, id, 2); + if (tex->dst_sel_w != 7) + notice_gpr_rel_write(usage, id, 3); + } else { + if (tex->dst_sel_x != 7) + notice_gpr_write(&usage[tex->dst_gpr], id, 0, predicate, -1); + if (tex->dst_sel_y != 7) + notice_gpr_write(&usage[tex->dst_gpr], id, 1, predicate, -1); + if (tex->dst_sel_z != 7) + notice_gpr_write(&usage[tex->dst_gpr], id, 2, predicate, -1); + if (tex->dst_sel_w != 7) + notice_gpr_write(&usage[tex->dst_gpr], id, 3, predicate, -1); + } +} + +static void notice_vtx_gprs(struct r600_bc_vtx *vtx, struct gpr_usage usage[128], + int32_t id, int predicate) +{ + notice_gpr_read(&usage[vtx->src_gpr], id, vtx->src_sel_x); + + if (vtx->dst_sel_x != 7) + notice_gpr_write(&usage[vtx->dst_gpr], id, 0, predicate, -1); + if (vtx->dst_sel_y != 7) + notice_gpr_write(&usage[vtx->dst_gpr], id, 1, predicate, -1); + if (vtx->dst_sel_z != 7) + notice_gpr_write(&usage[vtx->dst_gpr], id, 2, predicate, -1); + if (vtx->dst_sel_w != 7) + notice_gpr_write(&usage[vtx->dst_gpr], id, 3, predicate, -1); +} + +static void notice_export_gprs(struct r600_bc_cf *cf, struct gpr_usage usage[128], + struct r600_bc_cf *export_cf[128], int32_t export_remap[128]) +{ + //TODO handle other memory operations + struct gpr_usage *output = &usage[cf->output.gpr]; + int32_t id = (output->last_write[0] + 0x100) & ~0xFF; + + export_cf[cf->output.gpr] = cf; + export_remap[cf->output.gpr] = id; + if (cf->output.swizzle_x < 4) + notice_gpr_read(output, id, cf->output.swizzle_x); + if (cf->output.swizzle_y < 4) + notice_gpr_read(output, id, cf->output.swizzle_y); + if (cf->output.swizzle_z < 4) + notice_gpr_read(output, id, cf->output.swizzle_z); + if (cf->output.swizzle_w < 4) + notice_gpr_read(output, id, cf->output.swizzle_w); +} + +static struct gpr_usage_range *find_src_range(struct gpr_usage *usage, int32_t id) +{ + unsigned i; + for (i = 0; i < usage->nranges; ++i) { + struct gpr_usage_range* range = &usage->ranges[i]; + + if (range->start < id && id <= range->end) + return range; + } + return NULL; +} + +static struct gpr_usage_range *find_dst_range(struct gpr_usage *usage, int32_t id) +{ + unsigned i; + for (i = 0; i < usage->nranges; ++i) { + struct gpr_usage_range* range = &usage->ranges[i]; + int32_t end = range->end; + + if (range->start <= id && (id < end || end == -1)) + return range; + } + assert(0); /* should not happen */ + return NULL; +} + +static int is_barrier_needed(struct gpr_usage *usage, int32_t id, unsigned chan, int32_t last_barrier) +{ + if (usage->last_write[chan] != (id & ~0xFF)) + return usage->last_write[chan] >= last_barrier; + else + return 0; +} + +static int is_intersection(struct gpr_usage_range* a, struct gpr_usage_range* b) +{ + return a->start <= b->end && b->start < a->end; +} + +static int rate_replacement(struct gpr_usage *usage, struct gpr_usage_range* range) +{ + unsigned i; + int32_t best_start = 0x3FFFFFFF, best_end = 0x3FFFFFFF; + + for (i = 0; i < usage->nranges; ++i) { + if (usage->ranges[i].replacement != -1) + continue; /* ignore already remapped ranges */ + + if (is_intersection(&usage->ranges[i], range)) + return -1; /* forget it if usages overlap */ + + if (range->start >= usage->ranges[i].end) + best_start = MIN2(best_start, range->start - usage->ranges[i].end); + + if (range->end != -1 && range->end <= usage->ranges[i].start) + best_end = MIN2(best_end, usage->ranges[i].start - range->end); + } + return best_start + best_end; +} + +static void find_replacement(struct gpr_usage usage[128], unsigned current, + struct gpr_usage_range *range, int is_export) +{ + unsigned i; + int best_gpr = -1, best_rate = 0x7FFFFFFF; + + if (range->replacement != -1 && range->replacement <= current) { + struct gpr_usage_range *other = find_src_range(&usage[range->replacement], range->start); + if (other && other->replacement != -1) + range->replacement = other->replacement; + } + + if (range->replacement != -1 && range->replacement < current) { + int rate = rate_replacement(&usage[range->replacement], range); + + /* check if prefered replacement can be used */ + if (rate != -1) { + best_rate = rate; + best_gpr = range->replacement; + } + } + + if (best_gpr == -1 && (range->start & ~0xFF) == (range->end & ~0xFF)) { + /* register is just used inside one ALU clause */ + /* try to use clause temporaryis for it */ + for (i = 127; i > 123; --i) { + int rate = rate_replacement(&usage[i], range); + + if (rate == -1) /* can't be used because ranges overlap */ + continue; + + if (rate < best_rate) { + best_rate = rate; + best_gpr = i; + + /* can't get better than this */ + if (rate == 0 || is_export) + break; + } + } + } + + if (best_gpr == -1) { + for (i = 0; i < current; ++i) { + int rate = rate_replacement(&usage[i], range); + + if (rate == -1) /* can't be used because ranges overlap */ + continue; + + if (rate < best_rate) { + best_rate = rate; + best_gpr = i; + + /* can't get better than this */ + if (rate == 0) + break; + } + } + } + + range->replacement = best_gpr; + if (best_gpr != -1) { + struct gpr_usage_range *reservation = add_gpr_usage_range(&usage[best_gpr]); + reservation->replacement = -1; + reservation->start = range->start; + reservation->end = range->end; + } +} + +static void find_export_replacement(struct gpr_usage usage[128], + struct gpr_usage_range *range, struct r600_bc_cf *current, + struct r600_bc_cf *next, int32_t next_id) +{ + if (!next || next_id <= range->start || next_id > range->end) + return; + + if (current->output.type != next->output.type) + return; + + if ((current->output.array_base + 1) != next->output.array_base) + return; + + find_src_range(&usage[next->output.gpr], next_id)->replacement = range->replacement + 1; +} + +static void replace_alu_gprs(struct r600_bc_alu *alu, struct gpr_usage usage[128], + int32_t id, int32_t last_barrier, unsigned *barrier) +{ + struct gpr_usage *cur_usage; + struct gpr_usage_range *range; + unsigned src, num_src; + + num_src = r600_bc_get_num_operands(alu); + for (src = 0; src < num_src; ++src) { + // constants doesn't matter + if (!is_gpr(alu->src[src].sel)) + continue; + + cur_usage = &usage[alu->src[src].sel]; + range = find_src_range(cur_usage, id); + if (range->replacement != -1) + alu->src[src].sel = range->replacement; + + *barrier |= is_barrier_needed(cur_usage, id, alu->src[src].chan, last_barrier); + } + + if (alu->dst.write) { + cur_usage = &usage[alu->dst.sel]; + range = find_dst_range(cur_usage, id); + if (range->replacement == alu->dst.sel) { + if (!alu->is_op3) + alu->dst.write = 0; + else + /*TODO: really check that register 123 is useable */ + alu->dst.sel = 123; + } else if (range->replacement != -1) { + alu->dst.sel = range->replacement; + } + if (alu->dst.rel) + notice_gpr_rel_last_write(usage, id, alu->dst.chan); + else + notice_gpr_last_write(cur_usage, id, alu->dst.chan); + } +} + +static void replace_tex_gprs(struct r600_bc_tex *tex, struct gpr_usage usage[128], + int32_t id, int32_t last_barrier, unsigned *barrier) +{ + struct gpr_usage *cur_usage = &usage[tex->src_gpr]; + struct gpr_usage_range *range = find_src_range(cur_usage, id); + + if (tex->src_rel) { + *barrier = 1; + } else { + if (tex->src_sel_x < 4) + *barrier |= is_barrier_needed(cur_usage, id, tex->src_sel_x, last_barrier); + if (tex->src_sel_y < 4) + *barrier |= is_barrier_needed(cur_usage, id, tex->src_sel_y, last_barrier); + if (tex->src_sel_z < 4) + *barrier |= is_barrier_needed(cur_usage, id, tex->src_sel_z, last_barrier); + if (tex->src_sel_w < 4) + *barrier |= is_barrier_needed(cur_usage, id, tex->src_sel_w, last_barrier); + } + + if (range->replacement != -1) + tex->src_gpr = range->replacement; + + cur_usage = &usage[tex->dst_gpr]; + range = find_dst_range(cur_usage, id); + if (range->replacement != -1) + tex->dst_gpr = range->replacement; + + if (tex->dst_rel) { + if (tex->dst_sel_x != 7) + notice_gpr_rel_last_write(usage, id, tex->dst_sel_x); + if (tex->dst_sel_y != 7) + notice_gpr_rel_last_write(usage, id, tex->dst_sel_y); + if (tex->dst_sel_z != 7) + notice_gpr_rel_last_write(usage, id, tex->dst_sel_z); + if (tex->dst_sel_w != 7) + notice_gpr_rel_last_write(usage, id, tex->dst_sel_w); + } else { + if (tex->dst_sel_x != 7) + notice_gpr_last_write(cur_usage, id, tex->dst_sel_x); + if (tex->dst_sel_y != 7) + notice_gpr_last_write(cur_usage, id, tex->dst_sel_y); + if (tex->dst_sel_z != 7) + notice_gpr_last_write(cur_usage, id, tex->dst_sel_z); + if (tex->dst_sel_w != 7) + notice_gpr_last_write(cur_usage, id, tex->dst_sel_w); + } +} + +static void replace_vtx_gprs(struct r600_bc_vtx *vtx, struct gpr_usage usage[128], + int32_t id, int32_t last_barrier, unsigned *barrier) +{ + struct gpr_usage *cur_usage = &usage[vtx->src_gpr]; + struct gpr_usage_range *range = find_src_range(cur_usage, id); + + *barrier |= is_barrier_needed(cur_usage, id, vtx->src_sel_x, last_barrier); + + if (range->replacement != -1) + vtx->src_gpr = range->replacement; + + cur_usage = &usage[vtx->dst_gpr]; + range = find_dst_range(cur_usage, id); + if (range->replacement != -1) + vtx->dst_gpr = range->replacement; + + if (vtx->dst_sel_x != 7) + notice_gpr_last_write(cur_usage, id, vtx->dst_sel_x); + if (vtx->dst_sel_y != 7) + notice_gpr_last_write(cur_usage, id, vtx->dst_sel_y); + if (vtx->dst_sel_z != 7) + notice_gpr_last_write(cur_usage, id, vtx->dst_sel_z); + if (vtx->dst_sel_w != 7) + notice_gpr_last_write(cur_usage, id, vtx->dst_sel_w); +} + +static void replace_export_gprs(struct r600_bc_cf *cf, struct gpr_usage usage[128], + int32_t id, int32_t last_barrier) +{ + //TODO handle other memory operations + struct gpr_usage *cur_usage = &usage[cf->output.gpr]; + struct gpr_usage_range *range = find_src_range(cur_usage, id); + + cf->barrier = 0; + if (cf->output.swizzle_x < 4) + cf->barrier |= is_barrier_needed(cur_usage, -1, cf->output.swizzle_x, last_barrier); + if (cf->output.swizzle_y < 4) + cf->barrier |= is_barrier_needed(cur_usage, -1, cf->output.swizzle_y, last_barrier); + if (cf->output.swizzle_z < 4) + cf->barrier |= is_barrier_needed(cur_usage, -1, cf->output.swizzle_z, last_barrier); + if (cf->output.swizzle_w < 4) + cf->barrier |= is_barrier_needed(cur_usage, -1, cf->output.swizzle_w, last_barrier); + + if (range->replacement != -1) + cf->output.gpr = range->replacement; +} + +static void optimize_alu_inst(struct r600_bc_cf *cf, struct r600_bc_alu *alu) +{ + struct r600_bc_alu *alu_next; + unsigned chan; + unsigned src, num_src; + + /* check if a MOV could be optimized away */ + if (alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV) { + + /* destination equals source? */ + if (alu->dst.sel != alu->src[0].sel || + alu->dst.chan != alu->src[0].chan) + return; + + /* any special handling for the source? */ + if (alu->src[0].rel || alu->src[0].neg || alu->src[0].abs) + return; + + /* any special handling for destination? */ + if (alu->dst.rel || alu->dst.clamp) + return; + + /* ok find next instruction group and check if ps/pv is used */ + for (alu_next = alu; !alu_next->last; alu_next = NEXT_ALU(alu_next)); + + if (alu_next->list.next != &cf->alu) { + chan = is_alu_reduction_inst(alu) ? 0 : alu->dst.chan; + for (alu_next = NEXT_ALU(alu_next); alu_next; alu_next = NEXT_ALU(alu_next)) { + num_src = r600_bc_get_num_operands(alu_next); + for (src = 0; src < num_src; ++src) { + if (alu_next->src[src].sel == V_SQ_ALU_SRC_PV && + alu_next->src[src].chan == chan) + return; + + if (alu_next->src[src].sel == V_SQ_ALU_SRC_PS) + return; + } + + if (alu_next->last) + break; + } + } + + r600_bc_remove_alu(cf, alu); + } +} + +static void optimize_export_inst(struct r600_bc *bc, struct r600_bc_cf *cf) +{ + struct r600_bc_cf *prev = LIST_ENTRY(struct r600_bc_cf, cf->list.prev, list); + if (&prev->list == &bc->cf || + prev->inst != cf->inst || + prev->output.type != cf->output.type || + prev->output.elem_size != cf->output.elem_size || + prev->output.swizzle_x != cf->output.swizzle_x || + prev->output.swizzle_y != cf->output.swizzle_y || + prev->output.swizzle_z != cf->output.swizzle_z || + prev->output.swizzle_w != cf->output.swizzle_w) + return; + + if ((prev->output.burst_count + cf->output.burst_count) > 16) + return; + + if ((prev->output.gpr + prev->output.burst_count) == cf->output.gpr && + (prev->output.array_base + prev->output.burst_count) == cf->output.array_base) { + + prev->output.burst_count += cf->output.burst_count; + r600_bc_remove_cf(bc, cf); + + } else if (prev->output.gpr == (cf->output.gpr + cf->output.burst_count) && + prev->output.array_base == (cf->output.array_base + cf->output.burst_count)) { + + cf->output.burst_count += prev->output.burst_count; + r600_bc_remove_cf(bc, prev); + } +} + +static void r600_bc_optimize(struct r600_bc *bc) +{ + struct r600_bc_cf *cf, *next_cf; + struct r600_bc_alu *first, *next_alu; + struct r600_bc_alu *alu; + struct r600_bc_vtx *vtx; + struct r600_bc_tex *tex; + struct gpr_usage usage[128]; + + /* assume that each gpr is exported only once */ + struct r600_bc_cf *export_cf[128] = { NULL }; + int32_t export_remap[128]; + + int32_t id, barrier[bc->nstack]; + unsigned i, j, stack, predicate, old_stack; + + memset(&usage, 0, sizeof(usage)); + for (i = 0; i < 128; ++i) { + usage[i].first_write = -1; + usage[i].last_write[0] = -1; + usage[i].last_write[1] = -1; + usage[i].last_write[2] = -1; + usage[i].last_write[3] = -1; + } + + /* first gather some informations about the gpr usage */ + id = 0; stack = 0; + LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) { + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + predicate = 0; + first = NULL; + LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) { + if (!first) + first = alu; + notice_alu_src_gprs(alu, usage, id); + if (alu->last) { + notice_alu_dst_gprs(first, usage, id, predicate || stack > 0); + first = NULL; + ++id; + } + if (is_alu_pred_inst(alu)) + predicate++; + } + if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3) + stack += predicate; + else if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3) + stack -= 1; + else if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3) + stack -= 2; + break; + case CF_CLASS_TEXTURE: + LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) { + notice_tex_gprs(tex, usage, id++, stack > 0); + } + break; + case CF_CLASS_VERTEX: + LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { + notice_vtx_gprs(vtx, usage, id++, stack > 0); + } + break; + case CF_CLASS_EXPORT: + notice_export_gprs(cf, usage, export_cf, export_remap); + continue; // don't increment id + case CF_CLASS_OTHER: + switch (cf->inst) { + case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: + case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: + case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + break; + + case V_SQ_CF_WORD1_SQ_CF_INST_POP: + stack -= cf->pop_count; + break; + + default: + // TODO implement loop handling + goto out; + } + } + id += 0x100; + id &= ~0xFF; + } + assert(stack == 0); + + /* try to optimize gpr usage */ + for (i = 0; i < 124; ++i) { + for (j = 0; j < usage[i].nranges; ++j) { + struct gpr_usage_range *range = &usage[i].ranges[j]; + int is_export = export_cf[i] && export_cf[i + 1] && + range->start < export_remap[i] && + export_remap[i] <= range->end; + + if (range->start == -1) + range->replacement = -1; + else if (range->end == -1) + range->replacement = i; + else + find_replacement(usage, i, range, is_export); + + if (range->replacement == -1) + bc->ngpr = i; + else if (range->replacement < i && range->replacement > bc->ngpr) + bc->ngpr = range->replacement; + + if (is_export && range->replacement != -1) { + find_export_replacement(usage, range, export_cf[i], + export_cf[i + 1], export_remap[i + 1]); + } + } + } + bc->ngpr++; + + /* apply the changes */ + for (i = 0; i < 128; ++i) { + usage[i].last_write[0] = -1; + usage[i].last_write[1] = -1; + usage[i].last_write[2] = -1; + usage[i].last_write[3] = -1; + } + barrier[0] = 0; + id = 0; stack = 0; + LIST_FOR_EACH_ENTRY_SAFE(cf, next_cf, &bc->cf, list) { + old_stack = stack; + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + predicate = 0; + first = NULL; + cf->barrier = 0; + LIST_FOR_EACH_ENTRY_SAFE(alu, next_alu, &cf->alu, list) { + replace_alu_gprs(alu, usage, id, barrier[stack], &cf->barrier); + if (alu->last) + ++id; + + if (is_alu_pred_inst(alu)) + predicate++; + + if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3) + optimize_alu_inst(cf, alu); + } + if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3) + stack += predicate; + else if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER << 3) + stack -= 1; + else if (cf->inst == V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER << 3) + stack -= 2; + if (LIST_IS_EMPTY(&cf->alu)) { + r600_bc_remove_cf(bc, cf); + cf = NULL; + } + break; + case CF_CLASS_TEXTURE: + cf->barrier = 0; + LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) { + replace_tex_gprs(tex, usage, id++, barrier[stack], &cf->barrier); + } + break; + case CF_CLASS_VERTEX: + cf->barrier = 0; + LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { + replace_vtx_gprs(vtx, usage, id++, barrier[stack], &cf->barrier); + } + break; + case CF_CLASS_EXPORT: + continue; // don't increment id + case CF_CLASS_OTHER: + if (cf->inst == V_SQ_CF_WORD1_SQ_CF_INST_POP) { + cf->barrier = 0; + stack -= cf->pop_count; + } + break; + } + + id &= ~0xFF; + if (cf && cf->barrier) + barrier[old_stack] = id; + + for (i = old_stack + 1; i <= stack; ++i) + barrier[i] = barrier[old_stack]; + + id += 0x100; + if (stack != 0) /* ensue exports are placed outside of conditional blocks */ + continue; + + for (i = 0; i < 128; ++i) { + if (!export_cf[i] || id < export_remap[i]) + continue; + + r600_bc_move_cf(bc, export_cf[i], next_cf); + replace_export_gprs(export_cf[i], usage, export_remap[i], barrier[stack]); + if (export_cf[i]->barrier) + barrier[stack] = id - 1; + next_cf = LIST_ENTRY(struct r600_bc_cf, export_cf[i]->list.next, list); + optimize_export_inst(bc, export_cf[i]); + export_cf[i] = NULL; + } + } + assert(stack == 0); + +out: + for (i = 0; i < 128; ++i) { + free(usage[i].ranges); + } +} + int r600_bc_build(struct r600_bc *bc) { struct r600_bc_cf *cf; struct r600_bc_alu *alu; struct r600_bc_vtx *vtx; struct r600_bc_tex *tex; + struct r600_bc_cf *exports[4] = { NULL }; + uint32_t literal[4]; + unsigned nliteral; unsigned addr; - int r; + int i, r; if (bc->callstack[0].max > 0) bc->nstack = ((bc->callstack[0].max + 3) >> 2) + 2; @@ -926,35 +2151,37 @@ int r600_bc_build(struct r600_bc *bc) bc->nstack = 1; } + r600_bc_optimize(bc); + /* first path compute addr of each CF block */ /* addr start after all the CF instructions */ - addr = bc->cf_last->id + 2; + addr = LIST_ENTRY(struct r600_bc_cf, bc->cf.prev, list)->id + 2; LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) { - switch (cf->inst) { - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3): - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + nliteral = 0; + LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) { + r = r600_bc_alu_nliterals(alu, literal, &nliteral); + if (r) + return r; + if (alu->last) { + cf->ndw += align(nliteral, 2); + nliteral = 0; + } + } break; - case V_SQ_CF_WORD1_SQ_CF_INST_TEX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC: + case CF_CLASS_TEXTURE: + case CF_CLASS_VERTEX: /* fetch node need to be 16 bytes aligned*/ addr += 3; addr &= 0xFFFFFFFCUL; break; - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: - case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: - case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: break; - case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: - case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: - case V_SQ_CF_WORD1_SQ_CF_INST_POP: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: - case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: - case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: + case CF_CLASS_EXPORT: + if (cf->inst == BC_INST(bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT)) + exports[cf->output.type] = cf; + break; + case CF_CLASS_OTHER: break; default: R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst); @@ -964,6 +2191,14 @@ int r600_bc_build(struct r600_bc *bc) addr += cf->ndw; bc->ndw = cf->addr + cf->ndw; } + + /* set export done on last export of each type */ + for (i = 0; i < 4; ++i) { + if (exports[i]) { + exports[i]->inst = BC_INST(bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE); + } + } + free(bc->bytecode); bc->bytecode = calloc(1, bc->ndw * 4); if (bc->bytecode == NULL) @@ -976,10 +2211,14 @@ int r600_bc_build(struct r600_bc *bc) r = r600_bc_cf_build(bc, cf); if (r) return r; - switch (cf->inst) { - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3): - case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + nliteral = 0; LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) { + r = r600_bc_alu_nliterals(alu, literal, &nliteral); + if (r) + return r; + r600_bc_alu_adjust_literals(alu, literal, nliteral); switch(bc->chiprev) { case CHIPREV_R600: r = r600_bc_alu_build(bc, alu, addr); @@ -996,12 +2235,14 @@ int r600_bc_build(struct r600_bc *bc) return r; addr += 2; if (alu->last) { - addr += alu->nliteral; + for (i = 0; i < align(nliteral, 2); ++i) { + bc->bytecode[addr++] = literal[i]; + } + nliteral = 0; } } break; - case V_SQ_CF_WORD1_SQ_CF_INST_VTX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC: + case CF_CLASS_VERTEX: LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { r = r600_bc_vtx_build(bc, vtx, addr); if (r) @@ -1009,7 +2250,7 @@ int r600_bc_build(struct r600_bc *bc) addr += 4; } break; - case V_SQ_CF_WORD1_SQ_CF_INST_TEX: + case CF_CLASS_TEXTURE: LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) { r = r600_bc_tex_build(bc, tex, addr); if (r) @@ -1017,19 +2258,8 @@ int r600_bc_build(struct r600_bc *bc) addr += 4; } break; - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: - case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: - case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT: - case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: - case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: - case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: - case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: - case V_SQ_CF_WORD1_SQ_CF_INST_POP: - case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: - case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: + case CF_CLASS_EXPORT: + case CF_CLASS_OTHER: break; default: R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst); @@ -1077,7 +2307,14 @@ void r600_bc_clear(struct r600_bc *bc) void r600_bc_dump(struct r600_bc *bc) { - unsigned i; + struct r600_bc_cf *cf; + struct r600_bc_alu *alu; + struct r600_bc_vtx *vtx; + struct r600_bc_tex *tex; + + unsigned i, id; + uint32_t literal[4]; + unsigned nliteral; char chip = '6'; switch (bc->chiprev) { @@ -1092,11 +2329,124 @@ void r600_bc_dump(struct r600_bc *bc) chip = '6'; break; } - fprintf(stderr, "bytecode %d dw -----------------------\n", bc->ndw); + fprintf(stderr, "bytecode %d dw -- %d gprs -----------------------\n", bc->ndw, bc->ngpr); fprintf(stderr, " %c\n", chip); - for (i = 0; i < bc->ndw; i++) { - fprintf(stderr, "0x%08X\n", bc->bytecode[i]); + + LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) { + id = cf->id; + + switch (get_cf_class(cf)) { + case CF_CLASS_ALU: + fprintf(stderr, "%04d %08X ALU ", id, bc->bytecode[id]); + fprintf(stderr, "ADDR:%04d ", cf->addr); + fprintf(stderr, "KCACHE_MODE0:%X ", cf->kcache[0].mode); + fprintf(stderr, "KCACHE_BANK0:%X ", cf->kcache[0].bank); + fprintf(stderr, "KCACHE_BANK1:%X\n", cf->kcache[1].bank); + id++; + fprintf(stderr, "%04d %08X ALU ", id, bc->bytecode[id]); + fprintf(stderr, "INST:%d ", cf->inst); + fprintf(stderr, "KCACHE_MODE1:%X ", cf->kcache[1].mode); + fprintf(stderr, "KCACHE_ADDR0:%X ", cf->kcache[0].addr); + fprintf(stderr, "KCACHE_ADDR1:%X ", cf->kcache[1].addr); + fprintf(stderr, "BARRIER:%d ", cf->barrier); + fprintf(stderr, "COUNT:%d\n", cf->ndw / 2); + break; + case CF_CLASS_TEXTURE: + case CF_CLASS_VERTEX: + fprintf(stderr, "%04d %08X TEX/VTX ", id, bc->bytecode[id]); + fprintf(stderr, "ADDR:%04d\n", cf->addr); + id++; + fprintf(stderr, "%04d %08X TEX/VTX ", id, bc->bytecode[id]); + fprintf(stderr, "INST:%d ", cf->inst); + fprintf(stderr, "BARRIER:%d ", cf->barrier); + fprintf(stderr, "COUNT:%d\n", cf->ndw / 4); + break; + case CF_CLASS_EXPORT: + fprintf(stderr, "%04d %08X EXPORT ", id, bc->bytecode[id]); + fprintf(stderr, "GPR:%d ", cf->output.gpr); + fprintf(stderr, "ELEM_SIZE:%X ", cf->output.elem_size); + fprintf(stderr, "ARRAY_BASE:%X ", cf->output.array_base); + fprintf(stderr, "TYPE:%X\n", cf->output.type); + id++; + fprintf(stderr, "%04d %08X EXPORT ", id, bc->bytecode[id]); + fprintf(stderr, "SWIZ_X:%X ", cf->output.swizzle_x); + fprintf(stderr, "SWIZ_Y:%X ", cf->output.swizzle_y); + fprintf(stderr, "SWIZ_Z:%X ", cf->output.swizzle_z); + fprintf(stderr, "SWIZ_W:%X ", cf->output.swizzle_w); + fprintf(stderr, "SWIZ_W:%X ", cf->output.swizzle_w); + fprintf(stderr, "BARRIER:%d ", cf->barrier); + fprintf(stderr, "INST:%d ", cf->inst); + fprintf(stderr, "BURST_COUNT:%d\n", cf->output.burst_count); + break; + case CF_CLASS_OTHER: + fprintf(stderr, "%04d %08X CF ", id, bc->bytecode[id]); + fprintf(stderr, "ADDR:%04d\n", cf->cf_addr); + id++; + fprintf(stderr, "%04d %08X CF ", id, bc->bytecode[id]); + fprintf(stderr, "INST:%d ", cf->inst); + fprintf(stderr, "COND:%X ", cf->cond); + fprintf(stderr, "BARRIER:%d ", cf->barrier); + fprintf(stderr, "POP_COUNT:%X\n", cf->pop_count); + break; + } + + id = cf->addr; + nliteral = 0; + LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) { + r600_bc_alu_nliterals(alu, literal, &nliteral); + + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "SRC0(SEL:%d ", alu->src[0].sel); + fprintf(stderr, "REL:%d ", alu->src[0].rel); + fprintf(stderr, "CHAN:%d ", alu->src[0].chan); + fprintf(stderr, "NEG:%d) ", alu->src[0].neg); + fprintf(stderr, "SRC1(SEL:%d ", alu->src[1].sel); + fprintf(stderr, "REL:%d ", alu->src[1].rel); + fprintf(stderr, "CHAN:%d ", alu->src[1].chan); + fprintf(stderr, "NEG:%d) ", alu->src[1].neg); + fprintf(stderr, "LAST:%d)\n", alu->last); + id++; + fprintf(stderr, "%04d %08X %c ", id, bc->bytecode[id], alu->last ? '*' : ' '); + fprintf(stderr, "INST:%d ", alu->inst); + fprintf(stderr, "DST(SEL:%d ", alu->dst.sel); + fprintf(stderr, "CHAN:%d ", alu->dst.chan); + fprintf(stderr, "REL:%d ", alu->dst.rel); + fprintf(stderr, "CLAMP:%d) ", alu->dst.clamp); + fprintf(stderr, "BANK_SWIZZLE:%d ", alu->bank_swizzle); + if (alu->is_op3) { + fprintf(stderr, "SRC2(SEL:%d ", alu->src[2].sel); + fprintf(stderr, "REL:%d ", alu->src[2].rel); + fprintf(stderr, "CHAN:%d ", alu->src[2].chan); + fprintf(stderr, "NEG:%d)\n", alu->src[2].neg); + } else { + fprintf(stderr, "SRC0_ABS:%d ", alu->src[0].abs); + fprintf(stderr, "SRC1_ABS:%d ", alu->src[1].abs); + fprintf(stderr, "WRITE_MASK:%d ", alu->dst.write); + fprintf(stderr, "OMOD:%d ", alu->omod); + fprintf(stderr, "EXECUTE_MASK:%d ", alu->predicate); + fprintf(stderr, "UPDATE_PRED:%d\n", alu->predicate); + } + + id++; + if (alu->last) { + for (i = 0; i < nliteral; i++, id++) { + float *f = (float*)(bc->bytecode + id); + fprintf(stderr, "%04d %08X %f\n", id, bc->bytecode[id], *f); + } + id += nliteral & 1; + nliteral = 0; + } + } + + LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) { + //TODO + } + + LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { + //TODO + } } + fprintf(stderr, "--------------------------------------\n"); } @@ -1108,21 +2458,21 @@ void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) if (count > 8) { bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT(8 - 1); bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT(count - 8 - 1); } else { bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT(count - 1); } bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | - S_SQ_CF_WORD1_BARRIER(1); + S_SQ_CF_WORD1_BARRIER(0); rstate = &ve->rstate; rstate->id = R600_PIPE_STATE_FETCH_SHADER; @@ -1144,21 +2494,21 @@ void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned coun if (count > 8) { bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT(8 - 1); bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT((count - 8) - 1); } else { bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_BARRIER(0) | S_SQ_CF_WORD1_COUNT(count - 1); } bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | - S_SQ_CF_WORD1_BARRIER(1); + S_SQ_CF_WORD1_BARRIER(0); rstate = &ve->rstate; rstate->id = R600_PIPE_STATE_FETCH_SHADER; @@ -1308,31 +2658,6 @@ out_unknown: R600_ERR("unsupported vertex format %s\n", util_format_name(pformat)); } -static void r600_bc(unsigned ndw, unsigned chiprev, u32 *bytecode) -{ - unsigned i; - char chip = '6'; - - switch (chiprev) { - case 1: - chip = '7'; - break; - case 2: - chip = 'E'; - break; - case 0: - default: - chip = '6'; - break; - } - fprintf(stderr, "bytecode %d dw -----------------------\n", ndw); - fprintf(stderr, " %c\n", chip); - for (i = 0; i < ndw; i++) { - fprintf(stderr, "0x%08X\n", bytecode[i]); - } - fprintf(stderr, "--------------------------------------\n"); -} - int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, struct r600_vertex_element *ve) { unsigned ndw, i; diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h index a5504ad39f4..519245f3af2 100644 --- a/src/gallium/drivers/r600/r600_asm.h +++ b/src/gallium/drivers/r600/r600_asm.h @@ -25,9 +25,6 @@ #include "util/u_double_list.h" -#define NUM_OF_CYCLES 3 -#define NUM_OF_COMPONENTS 4 - struct r600_vertex_element; struct r600_pipe_context; @@ -37,6 +34,7 @@ struct r600_bc_alu_src { unsigned neg; unsigned abs; unsigned rel; + u32 *value; }; struct r600_bc_alu_dst { @@ -49,19 +47,15 @@ struct r600_bc_alu_dst { struct r600_bc_alu { struct list_head list; - struct list_head bs_list; /* bank swizzle list */ struct r600_bc_alu_src src[3]; struct r600_bc_alu_dst dst; unsigned inst; unsigned last; unsigned is_op3; unsigned predicate; - unsigned nliteral; - unsigned literal_added; unsigned bank_swizzle; unsigned bank_swizzle_force; - u32 value[4]; - int hw_gpr[NUM_OF_CYCLES][NUM_OF_COMPONENTS]; + unsigned omod; }; struct r600_bc_tex { @@ -114,15 +108,13 @@ struct r600_bc_vtx { struct r600_bc_output { unsigned array_base; unsigned type; - unsigned end_of_program; - unsigned inst; unsigned elem_size; unsigned gpr; unsigned swizzle_x; unsigned swizzle_y; unsigned swizzle_z; unsigned swizzle_w; - unsigned barrier; + unsigned burst_count; }; struct r600_bc_kcache { @@ -140,6 +132,7 @@ struct r600_bc_cf { unsigned cond; unsigned pop_count; unsigned cf_addr; /* control flow addr */ + unsigned barrier; struct r600_bc_kcache kcache[2]; unsigned r6xx_uses_waterfall; struct list_head alu; @@ -147,6 +140,8 @@ struct r600_bc_cf { struct list_head vtx; struct r600_bc_output output; struct r600_bc_alu *curr_bs_head; + struct r600_bc_alu *prev_bs_head; + struct r600_bc_alu *prev2_bs_head; }; #define FC_NONE 0 @@ -198,13 +193,13 @@ void eg_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); int r600_bc_init(struct r600_bc *bc, enum radeon_family family); void r600_bc_clear(struct r600_bc *bc); int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu); -int r600_bc_add_literal(struct r600_bc *bc, const u32 *value); int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx); int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex); int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output); int r600_bc_build(struct r600_bc *bc); int r600_bc_add_cfinst(struct r600_bc *bc, int inst); int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type); +void r600_bc_special_constants(u32 value, unsigned *sel, unsigned *neg); void r600_bc_dump(struct r600_bc *bc); void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 20838e4d98f..ad14dbe14f4 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -42,6 +42,7 @@ #include "r600_shader.h" #include "r600_pipe.h" #include "r600_state_inlines.h" +#include "r600_video_context.h" /* * pipe_context @@ -483,6 +484,7 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon) rscreen->screen.get_paramf = r600_get_paramf; rscreen->screen.is_format_supported = r600_is_format_supported; rscreen->screen.context_create = r600_create_context; + rscreen->screen.video_context_create = r600_video_create; r600_init_screen_resource_functions(&rscreen->screen); rscreen->tiling_info = r600_get_tiling_info(radeon); diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 2bf116c90bc..95367d7c536 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -225,21 +225,23 @@ int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) return 0; } -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader); +int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals); int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + u32 *literals; int r; //fprintf(stderr, "--------------------------------------------------------------\n"); //tgsi_dump(tokens, 0); shader->shader.family = r600_get_family(rctx->radeon); - r = r600_shader_from_tgsi(tokens, &shader->shader); + r = r600_shader_from_tgsi(tokens, &shader->shader, &literals); if (r) { R600_ERR("translation from TGSI failed !\n"); return r; } r = r600_bc_build(&shader->shader.bc); + free(literals); if (r) { R600_ERR("building bytecode failed !\n"); return r; @@ -272,7 +274,6 @@ struct r600_shader_ctx { struct r600_shader_tgsi_instruction *inst_info; struct r600_bc *bc; struct r600_shader *shader; - u32 value[4]; u32 *literals; u32 nliterals; u32 max_driver_temp_used; @@ -481,12 +482,12 @@ static int evergreen_gpr_count(struct r600_shader_ctx *ctx) return ctx->num_interp_gpr; } -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader) +int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals) { struct tgsi_full_immediate *immediate; struct r600_shader_ctx ctx; struct r600_bc_output output[32]; - unsigned output_done, noutput; + unsigned noutput; unsigned opcode; int i, r = 0, pos0; @@ -546,7 +547,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s * kcache banks later. */ ctx.file_offset[TGSI_FILE_CONSTANT] = 512; - ctx.file_offset[TGSI_FILE_IMMEDIATE] = 253; + ctx.file_offset[TGSI_FILE_IMMEDIATE] = V_SQ_ALU_SRC_LITERAL; ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] + ctx.info.file_count[TGSI_FILE_TEMPORARY]; @@ -589,9 +590,6 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s r = ctx.inst_info->process(&ctx); if (r) goto out_err; - r = r600_bc_add_literal(ctx.bc, ctx.value); - if (r) - goto out_err; break; case TGSI_TOKEN_TYPE_PROPERTY: break; @@ -611,10 +609,8 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[i].swizzle_y = 1; output[i].swizzle_z = 2; output[i].swizzle_w = 3; - output[i].barrier = 1; output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM; output[i].array_base = i - pos0; - output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT); switch (ctx.type) { case TGSI_PROCESSOR_VERTEX: if (shader->output[i].name == TGSI_SEMANTIC_POSITION) { @@ -674,10 +670,8 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[i].swizzle_y = 1; output[i].swizzle_z = 2; output[i].swizzle_w = 3; - output[i].barrier = 1; output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM; output[i].array_base = 0; - output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT); noutput++; } } @@ -690,29 +684,17 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[0].swizzle_y = 7; output[0].swizzle_z = 7; output[0].swizzle_w = 7; - output[0].barrier = 1; output[0].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL; output[0].array_base = 0; - output[0].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT); noutput++; } - /* set export done on last export of each type */ - for (i = noutput - 1, output_done = 0; i >= 0; i--) { - if (i == (noutput - 1)) { - output[i].end_of_program = 1; - } - if (!(output_done & (1 << output[i].type))) { - output_done |= (1 << output[i].type); - output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE); - } - } /* add output to bytecode */ for (i = 0; i < noutput; i++) { r = r600_bc_add_output(ctx.bc, &output[i]); if (r) goto out_err; } - free(ctx.literals); + *literals = ctx.literals; tgsi_parse_free(&ctx.parse); return 0; out_err: @@ -736,22 +718,29 @@ static int tgsi_src(struct r600_shader_ctx *ctx, const struct tgsi_full_src_register *tgsi_src, struct r600_bc_alu_src *r600_src) { - int index; memset(r600_src, 0, sizeof(struct r600_bc_alu_src)); - r600_src->sel = tgsi_src->Register.Index; + r600_src->neg = tgsi_src->Register.Negate; + r600_src->abs = tgsi_src->Register.Absolute; if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) { - r600_src->sel = 0; + int index; + if((tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleY) && + (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleZ) && + (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleW)) { + + index = tgsi_src->Register.Index * 4 + tgsi_src->Register.SwizzleX; + r600_bc_special_constants(ctx->literals[index], &r600_src->sel, &r600_src->neg); + if (r600_src->sel != V_SQ_ALU_SRC_LITERAL) + return 0; + } index = tgsi_src->Register.Index; - ctx->value[0] = ctx->literals[index * 4 + 0]; - ctx->value[1] = ctx->literals[index * 4 + 1]; - ctx->value[2] = ctx->literals[index * 4 + 2]; - ctx->value[3] = ctx->literals[index * 4 + 3]; + r600_src->sel = V_SQ_ALU_SRC_LITERAL; + r600_src->value = ctx->literals + index * 4; + } else { + if (tgsi_src->Register.Indirect) + r600_src->rel = V_SQ_REL_RELATIVE; + r600_src->sel = tgsi_src->Register.Index; + r600_src->sel += ctx->file_offset[tgsi_src->Register.File]; } - if (tgsi_src->Register.Indirect) - r600_src->rel = V_SQ_REL_RELATIVE; - r600_src->neg = tgsi_src->Register.Negate; - r600_src->abs = tgsi_src->Register.Absolute; - r600_src->sel += ctx->file_offset[tgsi_src->Register.File]; return 0; } @@ -839,18 +828,19 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx, struct r600_ int i, j, k, nliteral, r; for (i = 0, nliteral = 0; i < inst->Instruction.NumSrcRegs; i++) { - if (inst->Src[i].Register.File == TGSI_FILE_IMMEDIATE) { + if (r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) { nliteral++; } } for (i = 0, j = nliteral - 1; i < inst->Instruction.NumSrcRegs; i++) { - if (j > 0 && inst->Src[i].Register.File == TGSI_FILE_IMMEDIATE) { + if (j > 0 && r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) { int treg = r600_get_temp(ctx); for (k = 0; k < 4; k++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); alu.src[0].sel = r600_src[i].sel; alu.src[0].chan = k; + alu.src[0].value = r600_src[i].value; alu.dst.sel = treg; alu.dst.chan = k; alu.dst.write = 1; @@ -860,9 +850,6 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx, struct r600_ if (r) return r; } - r = r600_bc_add_literal(ctx->bc, &ctx->literals[inst->Src[i].Register.Index * 4]); - if (r) - return r; r600_src[i].sel = treg; j--; } @@ -870,19 +857,25 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx, struct r600_ return 0; } -static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap) +static int tgsi_last_instruction(unsigned writemask) { - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; - struct r600_bc_alu alu; - int i, j, r; - int lasti = 0; + int i, lasti = 0; for (i = 0; i < 4; i++) { - if (inst->Dst[0].Register.WriteMask & (1 << i)) { + if (writemask & (1 << i)) { lasti = i; } } + return lasti; +} + +static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + struct r600_bc_alu_src r600_src[3]; + struct r600_bc_alu alu; + int i, j, r; + int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); r = tgsi_split_constant(ctx, r600_src); if (r) @@ -951,12 +944,14 @@ static int tgsi_op2_swap(struct r600_shader_ctx *ctx) static int tgsi_setup_trig(struct r600_shader_ctx *ctx, struct r600_bc_alu_src r600_src[3]) { + static float half_inv_pi = 1.0 /(3.1415926535 * 2); + static float double_pi = 3.1415926535 * 2; + static float neg_pi = -3.1415926535; + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - int r, src0_chan; - uint32_t lit_vals[4]; + int r; struct r600_bc_alu alu; - memset(lit_vals, 0, 4*4); r = tgsi_split_constant(ctx, r600_src); if (r) return r; @@ -964,22 +959,6 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, if (r) return r; - src0_chan = tgsi_chan(&inst->Src[0], 0); - - /* We are going to feed two literals to the MAD below, - * which means that if the first operand is a literal as well, - * we need to copy its value manually. - */ - if (r600_src[0].sel == V_SQ_ALU_SRC_LITERAL) { - unsigned index = inst->Src[0].Register.Index; - - lit_vals[2] = ctx->literals[index * 4 + src0_chan]; - src0_chan = 2; - } - - lit_vals[0] = fui(1.0 /(3.1415926535 * 2)); - lit_vals[1] = fui(0.5f); - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); alu.is_op3 = 1; @@ -989,19 +968,17 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.dst.write = 1; alu.src[0] = r600_src[0]; - alu.src[0].chan = src0_chan; + alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); alu.src[1].sel = V_SQ_ALU_SRC_LITERAL; alu.src[1].chan = 0; - alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; + alu.src[1].value = (uint32_t *)&half_inv_pi; + alu.src[2].sel = V_SQ_ALU_SRC_0_5; alu.src[2].chan = 1; alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, lit_vals); - if (r) - return r; memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT); @@ -1017,14 +994,6 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, if (r) return r; - if (ctx->bc->chiprev == CHIPREV_R600) { - lit_vals[0] = fui(3.1415926535897f * 2.0f); - lit_vals[1] = fui(-3.1415926535897f); - } else { - lit_vals[0] = fui(1.0f); - lit_vals[1] = fui(-0.5f); - } - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); alu.is_op3 = 1; @@ -1040,13 +1009,20 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.src[1].chan = 0; alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 1; + + if (ctx->bc->chiprev == CHIPREV_R600) { + alu.src[1].value = (uint32_t *)&double_pi; + alu.src[2].value = (uint32_t *)&neg_pi; + } else { + alu.src[1].sel = V_SQ_ALU_SRC_1; + alu.src[2].sel = V_SQ_ALU_SRC_0_5; + alu.src[2].neg = 1; + } + alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, lit_vals); - if (r) - return r; return 0; } @@ -1056,7 +1032,7 @@ static int tgsi_trig(struct r600_shader_ctx *ctx) struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, r; - int lasti = 0; + int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); r = tgsi_setup_trig(ctx, r600_src); if (r) @@ -1076,10 +1052,6 @@ static int tgsi_trig(struct r600_shader_ctx *ctx) return r; /* replicate result */ - for (i = 0; i < 4; i++) { - if (inst->Dst[0].Register.WriteMask & (1 << i)) - lasti = i; - } for (i = 0; i < lasti + 1; i++) { if (!(inst->Dst[0].Register.WriteMask & (1 << i))) continue; @@ -1166,10 +1138,6 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* dst.w = 1.0; */ @@ -1190,10 +1158,6 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } return 0; @@ -1229,9 +1193,6 @@ static int tgsi_kill(struct r600_shader_ctx *ctx) if (r) return r; } - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* kill must be last in ALU */ ctx->bc->force_add_cf = 1; @@ -1294,10 +1255,6 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - if (inst->Dst[0].Register.WriteMask & (1 << 2)) { int chan; @@ -1316,10 +1273,6 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - chan = alu.dst.chan; sel = alu.dst.sel; @@ -1342,9 +1295,6 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* dst.z = exp(tmp.x) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); @@ -1388,9 +1338,6 @@ static int tgsi_rsq(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* replicate result */ return tgsi_helper_tempx_replicate(ctx); } @@ -1439,9 +1386,6 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* replicate result */ return tgsi_helper_tempx_replicate(ctx); } @@ -1465,9 +1409,6 @@ static int tgsi_pow(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc,ctx->value); - if (r) - return r; /* b * LOG2(a) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); @@ -1482,9 +1423,6 @@ static int tgsi_pow(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc,ctx->value); - if (r) - return r; /* POW(a,b) = EXP2(b * LOG2(a))*/ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); @@ -1495,9 +1433,6 @@ static int tgsi_pow(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc,ctx->value); - if (r) - return r; return tgsi_helper_tempx_replicate(ctx); } @@ -1537,9 +1472,6 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx) if (r) return r; } - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* dst = (-tmp > 0 ? -1 : tmp) */ for (i = 0; i < 4; i++) { @@ -1574,9 +1506,6 @@ static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instru struct r600_bc_alu alu; int i, r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; for (i = 0; i < 4; i++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); if (!(inst->Dst[0].Register.WriteMask & (1 << i))) { @@ -1606,13 +1535,7 @@ static int tgsi_op3(struct r600_shader_ctx *ctx) struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, j, r; - int lasti = 0; - - for (i = 0; i < 4; i++) { - if (inst->Dst[0].Register.WriteMask & (1 << i)) { - lasti = i; - } - } + int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); r = tgsi_split_constant(ctx, r600_src); if (r) @@ -1711,6 +1634,7 @@ static int tgsi_dp(struct r600_shader_ctx *ctx) static int tgsi_tex(struct r600_shader_ctx *ctx) { + static float one_point_five = 1.5f; struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_tex tex; struct r600_bc_alu alu; @@ -1720,7 +1644,6 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) boolean src_not_temp = inst->Src[0].Register.File != TGSI_FILE_TEMPORARY && inst->Src[0].Register.File != TGSI_FILE_INPUT; - uint32_t lit_vals[4]; src_gpr = ctx->file_offset[inst->Src[0].Register.File] + inst->Src[0].Register.Index; @@ -1869,6 +1792,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 0; + alu.src[2].value = (u32*)&one_point_five; alu.dst.sel = ctx->temp_reg; alu.dst.chan = 1; @@ -1879,11 +1803,6 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) if (r) return r; - lit_vals[0] = fui(1.5f); - - r = r600_bc_add_literal(ctx->bc, lit_vals); - if (r) - return r; src_not_temp = FALSE; src_gpr = ctx->temp_reg; } @@ -1956,6 +1875,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; + int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); unsigned i; int r; @@ -1965,8 +1885,40 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) r = tgsi_split_literal_constant(ctx, r600_src); if (r) return r; + + /* optimize if it's just an equal balance */ + if(r600_src[0].sel == V_SQ_ALU_SRC_0_5) { + for (i = 0; i < lasti + 1; i++) { + if (!(inst->Dst[0].Register.WriteMask & (1 << i))) + continue; + + memset(&alu, 0, sizeof(struct r600_bc_alu)); + alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD); + alu.src[0] = r600_src[1]; + alu.src[0].chan = tgsi_chan(&inst->Src[1], i); + alu.src[1] = r600_src[2]; + alu.src[1].chan = tgsi_chan(&inst->Src[2], i); + alu.omod = 3; + r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); + if (r) + return r; + + alu.dst.chan = i; + if (i == lasti) { + alu.last = 1; + } + r = r600_bc_add_alu(ctx->bc, &alu); + if (r) + return r; + } + return 0; + } + /* 1 - src0 */ - for (i = 0; i < 4; i++) { + for (i = 0; i < lasti + 1; i++) { + if (!(inst->Dst[0].Register.WriteMask & (1 << i))) + continue; + memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD); alu.src[0].sel = V_SQ_ALU_SRC_1; @@ -1976,7 +1928,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) alu.src[1].neg = 1; alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; - if (i == 3) { + if (i == lasti) { alu.last = 1; } alu.dst.write = 1; @@ -1984,12 +1936,12 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) if (r) return r; } - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* (1 - src0) * src2 */ - for (i = 0; i < 4; i++) { + for (i = 0; i < lasti + 1; i++) { + if (!(inst->Dst[0].Register.WriteMask & (1 << i))) + continue; + memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); alu.src[0].sel = ctx->temp_reg; @@ -1998,7 +1950,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) alu.src[1].chan = tgsi_chan(&inst->Src[2], i); alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; - if (i == 3) { + if (i == lasti) { alu.last = 1; } alu.dst.write = 1; @@ -2006,12 +1958,12 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) if (r) return r; } - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; /* src0 * src1 + (1 - src0) * src2 */ - for (i = 0; i < 4; i++) { + for (i = 0; i < lasti + 1; i++) { + if (!(inst->Dst[0].Register.WriteMask & (1 << i))) + continue; + memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); alu.is_op3 = 1; @@ -2021,16 +1973,20 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) alu.src[1].chan = tgsi_chan(&inst->Src[1], i); alu.src[2].sel = ctx->temp_reg; alu.src[2].chan = i; - alu.dst.sel = ctx->temp_reg; + + r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); + if (r) + return r; + alu.dst.chan = i; - if (i == 3) { + if (i == lasti) { alu.last = 1; } r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; } - return tgsi_helper_copy(ctx, inst); + return 0; } static int tgsi_cmp(struct r600_shader_ctx *ctx) @@ -2039,13 +1995,7 @@ static int tgsi_cmp(struct r600_shader_ctx *ctx) struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, r; - int lasti = 0; - - for (i = 0; i < 4; i++) { - if (inst->Dst[0].Register.WriteMask & (1 << i)) { - lasti = i; - } - } + int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); r = tgsi_split_constant(ctx, r600_src); if (r) @@ -2148,10 +2098,6 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } for (i = 0; i < 4; i++) { @@ -2209,10 +2155,6 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } if (use_temp) return tgsi_helper_copy(ctx, inst); @@ -2245,10 +2187,6 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; @@ -2260,10 +2198,6 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.y = tmp - floor(tmp); */ @@ -2289,9 +2223,6 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.z = RoughApprox2ToX(tmp);*/ @@ -2312,9 +2243,6 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.w = 1.0;*/ @@ -2332,9 +2260,6 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } return tgsi_helper_copy(ctx, inst); } @@ -2364,10 +2289,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; @@ -2380,10 +2301,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.y = src.x / (2 ^ floor(log2(src.x))); */ @@ -2406,10 +2323,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR); @@ -2425,10 +2338,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); @@ -2444,10 +2353,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE); @@ -2463,10 +2368,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) if (r) return r; - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); @@ -2488,10 +2389,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.z = log2(src);*/ @@ -2513,10 +2410,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } /* result.w = 1.0; */ @@ -2535,10 +2428,6 @@ static int tgsi_log(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - - r = r600_bc_add_literal(ctx->bc, ctx->value); - if (r) - return r; } return tgsi_helper_copy(ctx, inst); @@ -2693,9 +2582,25 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode) static int pops(struct r600_shader_ctx *ctx, int pops) { - r600_bc_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_POP)); - ctx->bc->cf_last->pop_count = pops; - ctx->bc->cf_last->cf_addr = ctx->bc->cf_last->id + 2; + int alu_pop = 3; + if (ctx->bc->cf_last) { + if (ctx->bc->cf_last->inst == CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU) << 3) + alu_pop = 0; + else if (ctx->bc->cf_last->inst == CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER) << 3) + alu_pop = 1; + } + alu_pop += pops; + if (alu_pop == 1) { + ctx->bc->cf_last->inst = CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP_AFTER) << 3; + ctx->bc->force_add_cf = 1; + } else if (alu_pop == 2) { + ctx->bc->cf_last->inst = CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_POP2_AFTER) << 3; + ctx->bc->force_add_cf = 1; + } else { + r600_bc_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_POP)); + ctx->bc->cf_last->pop_count = pops; + ctx->bc->cf_last->cf_addr = ctx->bc->cf_last->id + 2; + } return 0; } diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index 35b0331525a..935dd6fe3ab 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -47,6 +47,6 @@ struct r600_shader { boolean uses_kill; }; -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader); +int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals); #endif diff --git a/src/gallium/drivers/r600/r600_sq.h b/src/gallium/drivers/r600/r600_sq.h index d812bfd1fed..56ed35e8b32 100644 --- a/src/gallium/drivers/r600/r600_sq.h +++ b/src/gallium/drivers/r600/r600_sq.h @@ -191,6 +191,8 @@ #define V_SQ_ALU_SRC_M_1_INT 0x000000FB #define V_SQ_ALU_SRC_0_5 0x000000FC #define V_SQ_ALU_SRC_LITERAL 0x000000FD +#define V_SQ_ALU_SRC_PV 0x000000FE +#define V_SQ_ALU_SRC_PS 0x000000FF #define V_SQ_ALU_SRC_PARAM_BASE 0x000001C0 #define S_SQ_ALU_WORD0_SRC0_REL(x) (((x) & 0x1) << 9) #define G_SQ_ALU_WORD0_SRC0_REL(x) (((x) >> 9) & 0x1) diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 96b02d72b94..9572ff9a1a2 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -925,6 +925,17 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta desc = util_format_description(rtex->resource.base.b.format); if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) ntype = V_0280A0_NUMBER_SRGB; + else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) { + switch(desc->channel[0].type) { + case UTIL_FORMAT_TYPE_UNSIGNED: + ntype = V_0280A0_NUMBER_UNORM; + break; + + case UTIL_FORMAT_TYPE_SIGNED: + ntype = V_0280A0_NUMBER_SNORM; + break; + } + } format = r600_translate_colorformat(rtex->resource.base.b.format); swap = r600_translate_colorswap(rtex->resource.base.b.format); diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h index d994196e19d..39ca0a74f3f 100644 --- a/src/gallium/drivers/r600/r600_state_inlines.h +++ b/src/gallium/drivers/r600/r600_state_inlines.h @@ -310,6 +310,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) return V_0280A0_SWAP_STD; case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_R16_SNORM: return V_0280A0_SWAP_STD; /* 32-bit buffers. */ @@ -360,7 +361,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) // return FMT_16_16_16_16_FLOAT; /* 128-bit buffers. */ - case PIPE_FORMAT_R32G32B32A32_FLOAT: + //case PIPE_FORMAT_R32G32B32A32_FLOAT: // return FMT_32_32_32_32_FLOAT; return 0; default: @@ -401,6 +402,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_0280A0_COLOR_8_8; case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_R16_SNORM: return V_0280A0_COLOR_16; /* 32-bit buffers. */ @@ -433,8 +435,8 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_S8_USCALED_Z24_UNORM: return V_0280A0_COLOR_24_8; - case PIPE_FORMAT_R32_FLOAT: - return V_0280A0_COLOR_32_FLOAT; + //case PIPE_FORMAT_R32_FLOAT: + // return V_0280A0_COLOR_32_FLOAT; case PIPE_FORMAT_R16G16_FLOAT: return V_0280A0_COLOR_16_16_FLOAT; @@ -465,10 +467,10 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_0280A0_COLOR_32_32; /* 128-bit buffers. */ - case PIPE_FORMAT_R32G32B32_FLOAT: - return V_0280A0_COLOR_32_32_32_FLOAT; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - return V_0280A0_COLOR_32_32_32_32_FLOAT; + //case PIPE_FORMAT_R32G32B32_FLOAT: + // return V_0280A0_COLOR_32_32_32_FLOAT; + //case PIPE_FORMAT_R32G32B32A32_FLOAT: + // return V_0280A0_COLOR_32_32_32_32_FLOAT; /* YUV buffers. */ case PIPE_FORMAT_UYVY: diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index e2745624575..1f4f453c091 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -321,6 +321,48 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } +/* Figure out whether u_blitter will fallback to a transfer operation. + * If so, don't use a staging resource. + */ +static boolean permit_hardware_blit(struct pipe_screen *screen, + const struct pipe_resource *res) +{ + unsigned bind; + + if (util_format_is_depth_or_stencil(res->format)) + bind = PIPE_BIND_DEPTH_STENCIL; + else + bind = PIPE_BIND_RENDER_TARGET; + + /* See r600_resource_copy_region: there is something wrong + * with depth resource copies at the moment so avoid them for + * now. + */ + if (util_format_get_component_bits(res->format, + UTIL_FORMAT_COLORSPACE_ZS, + 0) != 0) + return FALSE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + bind, 0)) + return FALSE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + PIPE_BIND_SAMPLER_VIEW, 0)) + return FALSE; + + if (res->usage == PIPE_USAGE_STREAM) + return FALSE; + + return TRUE; +} + struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { @@ -332,7 +374,7 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, if (force_tiling == -1) force_tiling = debug_get_bool_option("R600_FORCE_TILING", FALSE); - if (force_tiling) { + if (force_tiling && permit_hardware_blit(screen, templ)) { if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && !(templ->bind & PIPE_BIND_SCANOUT)) { array_mode = V_038000_ARRAY_2D_TILED_THIN1; @@ -485,46 +527,6 @@ static INLINE unsigned u_box_volume( const struct pipe_box *box ) return box->width * box->depth * box->height; }; - -/* Figure out whether u_blitter will fallback to a transfer operation. - * If so, don't use a staging resource. - */ -static boolean permit_hardware_blit(struct pipe_screen *screen, - struct pipe_resource *res) -{ - unsigned bind; - - if (util_format_is_depth_or_stencil(res->format)) - bind = PIPE_BIND_DEPTH_STENCIL; - else - bind = PIPE_BIND_RENDER_TARGET; - - /* See r600_resource_copy_region: there is something wrong - * with depth resource copies at the moment so avoid them for - * now. - */ - if (util_format_get_component_bits(res->format, - UTIL_FORMAT_COLORSPACE_ZS, - 0) != 0) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - bind, 0)) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - PIPE_BIND_SAMPLER_VIEW, 0)) - return FALSE; - - return TRUE; -} - struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, @@ -794,7 +796,7 @@ static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format, /* texture format translate */ uint32_t r600_translate_texformat(enum pipe_format format, - const unsigned char *swizzle_view, + const unsigned char *swizzle_view, uint32_t *word4_p, uint32_t *yuv_format_p) { uint32_t result = 0, word4 = 0, yuv_format = 0; @@ -848,7 +850,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, break; } goto out_unknown; /* TODO */ - + case UTIL_FORMAT_COLORSPACE_SRGB: word4 |= S_038010_FORCE_DEGAMMA(1); if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB) @@ -864,7 +866,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, static int r600_enable_s3tc = -1; if (r600_enable_s3tc == -1) - r600_enable_s3tc = + r600_enable_s3tc = debug_get_bool_option("R600_ENABLE_S3TC", FALSE); if (!r600_enable_s3tc) @@ -887,7 +889,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, } - for (i = 0; i < desc->nr_channels; i++) { + for (i = 0; i < desc->nr_channels; i++) { if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { word4 |= sign_bit[i]; } @@ -901,7 +903,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, for (i = 1; i < desc->nr_channels; i++) { uniform = uniform && desc->channel[0].size == desc->channel[i].size; } - + /* Non-uniform formats. */ if (!uniform) { switch(desc->nr_channels) { @@ -1019,7 +1021,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, goto out_word4; } } - + } out_word4: if (word4_p) diff --git a/src/gallium/drivers/r600/r600_video_context.c b/src/gallium/drivers/r600/r600_video_context.c new file mode 100644 index 00000000000..b3885db0f55 --- /dev/null +++ b/src/gallium/drivers/r600/r600_video_context.c @@ -0,0 +1,21 @@ +#include "r600_video_context.h" +#include <softpipe/sp_video_context.h> + +struct pipe_video_context * +r600_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv) +{ + struct pipe_context *pipe; + + assert(screen); + + pipe = screen->context_create(screen, priv); + if (!pipe) + return NULL; + + return sp_video_create_ex(pipe, profile, chroma_format, width, height, + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE, + true, + PIPE_FORMAT_VUYX); +} diff --git a/src/gallium/drivers/r600/r600_video_context.h b/src/gallium/drivers/r600/r600_video_context.h new file mode 100644 index 00000000000..bda33a00d44 --- /dev/null +++ b/src/gallium/drivers/r600/r600_video_context.h @@ -0,0 +1,11 @@ +#ifndef __R600_VIDEO_CONTEXT_H__ +#define __R600_VIDEO_CONTEXT_H__ + +#include <pipe/p_video_context.h> + +struct pipe_video_context * +r600_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv); + +#endif diff --git a/src/gallium/drivers/r600/r700_asm.c b/src/gallium/drivers/r600/r700_asm.c index 892dee86baf..a7f2f54736e 100644 --- a/src/gallium/drivers/r600/r700_asm.c +++ b/src/gallium/drivers/r600/r700_asm.c @@ -29,8 +29,6 @@ int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id) { - unsigned i; - bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) | S_SQ_ALU_WORD0_SRC0_REL(alu->src[0].rel) | S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) | @@ -61,18 +59,11 @@ int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id) S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) | S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) | S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) | + S_SQ_ALU_WORD1_OP2_OMOD(alu->omod) | S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) | S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle) | S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) | S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate); } - if (alu->last) { - if (alu->nliteral && !alu->literal_added) { - R600_ERR("Bug in ALU processing for instruction 0x%08x, literal not added correctly\n", alu->inst); - } - for (i = 0; i < alu->nliteral; i++) { - bc->bytecode[id++] = alu->value[i]; - } - } return 0; } diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index 28953582f0a..8876bd16398 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -19,7 +19,7 @@ C_SOURCES = \ sp_quad_fs.c \ sp_quad_blend.c \ sp_screen.c \ - sp_setup.c \ + sp_setup.c \ sp_state_blend.c \ sp_state_clip.c \ sp_state_derived.c \ @@ -33,6 +33,7 @@ C_SOURCES = \ sp_tex_sample.c \ sp_tex_tile_cache.c \ sp_tile_cache.c \ - sp_surface.c + sp_surface.c \ + sp_video_context.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index ea10e8a9f98..9b2abdfd7f1 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -35,6 +35,7 @@ softpipe = env.ConvenienceLibrary( 'sp_tex_tile_cache.c', 'sp_texture.c', 'sp_tile_cache.c', + 'sp_video_context.c', ]) env.Alias('softpipe', softpipe) diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index cbdea19af43..cd3b6240fe9 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -39,6 +39,7 @@ #include "sp_texture.h" #include "sp_screen.h" #include "sp_context.h" +#include "sp_video_context.h" #include "sp_fence.h" #include "sp_public.h" @@ -304,6 +305,7 @@ softpipe_create_screen(struct sw_winsys *winsys) screen->base.is_format_supported = softpipe_is_format_supported; screen->base.context_create = softpipe_create_context; screen->base.flush_frontbuffer = softpipe_flush_frontbuffer; + screen->base.video_context_create = sp_video_create; util_format_s3tc_init(); diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 5603110eeb3..533d6252e25 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -79,7 +79,6 @@ struct softpipe_transfer }; - /** cast wrappers */ static INLINE struct softpipe_resource * softpipe_resource(struct pipe_resource *pt) diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c new file mode 100644 index 00000000000..daebbc54ad8 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_video_context.c @@ -0,0 +1,648 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_inlines.h" +#include "util/u_memory.h" + +#include "sp_video_context.h" +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include <util/u_keymap.h> +#include <util/u_rect.h> +#include <util/u_video.h> +#include <util/u_surface.h> +#include "sp_public.h" +#include "sp_texture.h" + +#define NUM_BUFFERS 2 + +static void +flush_buffer(struct sp_mpeg12_context *ctx) +{ + assert(ctx); + + if(ctx->mc_buffer != NULL) { + + vl_mpeg12_mc_unmap_buffer(&ctx->mc_renderer, ctx->mc_buffer); + vl_mpeg12_mc_renderer_flush(&ctx->mc_renderer, ctx->mc_buffer); + + ctx->mc_buffer = NULL; + } +} + +static void +rotate_buffer(struct sp_mpeg12_context *ctx) +{ + static unsigned key = 0; + struct vl_mpeg12_mc_buffer *buffer; + + assert(ctx); + + flush_buffer(ctx); + + buffer = (struct vl_mpeg12_mc_buffer*)util_keymap_lookup(ctx->buffer_map, &key); + if (!buffer) { + boolean added_to_map; + + buffer = CALLOC_STRUCT(vl_mpeg12_mc_buffer); + if (buffer == NULL) + return; + + if(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, buffer)) { + FREE(buffer); + return; + } + + added_to_map = util_keymap_insert(ctx->buffer_map, &key, buffer, ctx); + assert(added_to_map); + } + ++key; + key %= NUM_BUFFERS; + ctx->mc_buffer = buffer; + + vl_mpeg12_mc_map_buffer(&ctx->mc_renderer, ctx->mc_buffer); +} + +static void +delete_buffer(const struct keymap *map, + const void *key, void *data, + void *user) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)user; + struct vl_mpeg12_mc_buffer *buf = (struct vl_mpeg12_mc_buffer*)data; + + assert(map); + assert(key); + assert(data); + assert(user); + + vl_mpeg12_mc_cleanup_buffer(&ctx->mc_renderer, buf); +} + +static void +sp_mpeg12_destroy(struct pipe_video_context *vpipe) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + + flush_buffer(ctx); + + /* Asserted in softpipe_delete_fs_state() for some reason */ + ctx->pipe->bind_vs_state(ctx->pipe, NULL); + ctx->pipe->bind_fs_state(ctx->pipe, NULL); + + ctx->pipe->delete_blend_state(ctx->pipe, ctx->blend); + ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast); + ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa); + + pipe_surface_reference(&ctx->decode_target, NULL); + vl_compositor_cleanup(&ctx->compositor); + util_delete_keymap(ctx->buffer_map, ctx); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + + FREE(ctx); +} + +static int +sp_mpeg12_get_param(struct pipe_video_context *vpipe, int param) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + + switch (param) { + case PIPE_CAP_NPOT_TEXTURES: + /* XXX: Temporary; not all paths are NPOT-tested */ +#if 0 + return ctx->pipe->screen->get_param(ctx->pipe->screen, param); +#endif + return FALSE; + case PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT: + return ctx->decode_format; + default: + { + debug_printf("Softpipe: Unknown PIPE_CAP %d\n", param); + return 0; + } + } +} + +static struct pipe_surface * +sp_mpeg12_create_surface(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + const struct pipe_surface *templat) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + + return ctx->pipe->create_surface(ctx->pipe, resource, templat); +} + +static boolean +sp_mpeg12_is_format_supported(struct pipe_video_context *vpipe, + enum pipe_format format, + unsigned usage, + unsigned geom) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + + /* XXX: Temporary; not all paths are NPOT-tested */ + if (geom & PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO) + return FALSE; + + + return ctx->pipe->screen->is_format_supported(ctx->pipe->screen, format, PIPE_TEXTURE_2D, + 0, usage, geom); +} + +static void +sp_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe, + struct pipe_surface *past, + struct pipe_surface *future, + unsigned num_macroblocks, + struct pipe_macroblock *macroblocks, + struct pipe_fence_handle **fence) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + struct pipe_mpeg12_macroblock *mpeg12_macroblocks = (struct pipe_mpeg12_macroblock*)macroblocks; + + assert(vpipe); + assert(num_macroblocks); + assert(macroblocks); + assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12); + assert(ctx->decode_target); + assert(ctx->mc_buffer); + + vl_mpeg12_mc_renderer_render_macroblocks(&ctx->mc_renderer, + ctx->mc_buffer, + ctx->decode_target, + past, future, num_macroblocks, + mpeg12_macroblocks, fence); +} + +static void +sp_mpeg12_clear_render_target(struct pipe_video_context *vpipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + float rgba[4] = { 0, 0, 0, 0 }; + + assert(vpipe); + assert(dst); + + if (ctx->pipe->clear_render_target) + ctx->pipe->clear_render_target(ctx->pipe, dst, rgba, dstx, dsty, width, height); + else + util_clear_render_target(ctx->pipe, dst, rgba, dstx, dsty, width, height); +} + +static void +sp_mpeg12_resource_copy_region(struct pipe_video_context *vpipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + struct pipe_surface *src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(dst); + + struct pipe_box box; + box.x = srcx; + box.y = srcy; + box.z = 0; + box.width = width; + box.height = height; + + if (ctx->pipe->resource_copy_region) + ctx->pipe->resource_copy_region(ctx->pipe, dst->texture, dst->u.tex.level, + dstx, dsty, dst->u.tex.first_layer, + src->texture, src->u.tex.level, &box); + else + util_resource_copy_region(ctx->pipe, dst->texture, dst->u.tex.level, + dstx, dsty, dst->u.tex.first_layer, + src->texture, src->u.tex.level, &box); +} + +static struct pipe_transfer* +sp_mpeg12_get_transfer(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ + const struct pipe_box *box) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(resource); + assert(box); + + return ctx->pipe->get_transfer(ctx->pipe, resource, level, usage, box); +} + +static void +sp_mpeg12_transfer_destroy(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(transfer); + + ctx->pipe->transfer_destroy(ctx->pipe, transfer); +} + +static void* +sp_mpeg12_transfer_map(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(transfer); + + return ctx->pipe->transfer_map(ctx->pipe, transfer); +} + +static void +sp_mpeg12_transfer_flush_region(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(transfer); + assert(box); + + ctx->pipe->transfer_flush_region(ctx->pipe, transfer, box); +} + +static void +sp_mpeg12_transfer_unmap(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(transfer); + + ctx->pipe->transfer_unmap(ctx->pipe, transfer); +} + +static void +sp_mpeg12_transfer_inline_write(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned slice_stride) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(resource); + assert(box); + assert(data); + assert(ctx->pipe->transfer_inline_write); + + ctx->pipe->transfer_inline_write(ctx->pipe, resource, level, usage, + box, data, stride, slice_stride); +} + +static void +sp_mpeg12_render_picture(struct pipe_video_context *vpipe, + struct pipe_surface *src_surface, + enum pipe_mpeg12_picture_type picture_type, + /*unsigned num_past_surfaces, + struct pipe_surface *past_surfaces, + unsigned num_future_surfaces, + struct pipe_surface *future_surfaces,*/ + struct pipe_video_rect *src_area, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(src_surface); + assert(src_area); + assert(dst_surface); + assert(dst_area); + + flush_buffer(ctx); + + vl_compositor_render(&ctx->compositor, src_surface, + picture_type, src_area, dst_surface, dst_area, fence); +} + +static void +sp_mpeg12_set_picture_background(struct pipe_video_context *vpipe, + struct pipe_surface *bg, + struct pipe_video_rect *bg_src_rect) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(bg); + assert(bg_src_rect); + + vl_compositor_set_background(&ctx->compositor, bg, bg_src_rect); +} + +static void +sp_mpeg12_set_picture_layers(struct pipe_video_context *vpipe, + struct pipe_surface *layers[], + struct pipe_video_rect *src_rects[], + struct pipe_video_rect *dst_rects[], + unsigned num_layers) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert((layers && src_rects && dst_rects) || + (!layers && !src_rects && !dst_rects)); + + vl_compositor_set_layers(&ctx->compositor, layers, src_rects, dst_rects, num_layers); +} + +static void +sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe, + struct pipe_surface *dt) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + assert(dt); + + if (ctx->decode_target != dt || ctx->mc_buffer == NULL) { + rotate_buffer(ctx); + + pipe_surface_reference(&ctx->decode_target, dt); + } +} + +static void +sp_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, const float *mat) +{ + struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe; + + assert(vpipe); + + vl_compositor_set_csc_matrix(&ctx->compositor, mat); +} + +static bool +init_pipe_state(struct sp_mpeg12_context *ctx) +{ + struct pipe_rasterizer_state rast; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + unsigned i; + + assert(ctx); + + memset(&rast, 0, sizeof rast); + rast.flatshade = 1; + rast.flatshade_first = 0; + rast.light_twoside = 0; + rast.front_ccw = 1; + rast.cull_face = PIPE_FACE_NONE; + rast.fill_back = PIPE_POLYGON_MODE_FILL; + rast.fill_front = PIPE_POLYGON_MODE_FILL; + rast.offset_point = 0; + rast.offset_line = 0; + rast.scissor = 0; + rast.poly_smooth = 0; + rast.poly_stipple_enable = 0; + rast.sprite_coord_enable = 0; + rast.point_size_per_vertex = 0; + rast.multisample = 0; + rast.line_smooth = 0; + rast.line_stipple_enable = 0; + rast.line_stipple_factor = 0; + rast.line_stipple_pattern = 0; + rast.line_last_pixel = 0; + rast.line_width = 1; + rast.point_smooth = 0; + rast.point_quad_rasterization = 0; + rast.point_size_per_vertex = 1; + rast.offset_units = 1; + rast.offset_scale = 1; + rast.gl_rasterization_rules = 1; + + ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast); + ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast); + + memset(&blend, 0, sizeof blend); + + blend.independent_blend_enable = 0; + blend.rt[0].blend_enable = 0; + blend.rt[0].rgb_func = PIPE_BLEND_ADD; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_func = PIPE_BLEND_ADD; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + /* Needed to allow color writes to FB, even if blending disabled */ + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.dither = 0; + ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend); + ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend); + + memset(&dsa, 0, sizeof dsa); + dsa.depth.enabled = 0; + dsa.depth.writemask = 0; + dsa.depth.func = PIPE_FUNC_ALWAYS; + for (i = 0; i < 2; ++i) { + dsa.stencil[i].enabled = 0; + dsa.stencil[i].func = PIPE_FUNC_ALWAYS; + dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].valuemask = 0; + dsa.stencil[i].writemask = 0; + } + dsa.alpha.enabled = 0; + dsa.alpha.func = PIPE_FUNC_ALWAYS; + dsa.alpha.ref_value = 0; + ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa); + ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa); + + return true; +} + +static struct pipe_video_context * +sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode, + bool pot_buffers, + enum pipe_format decode_format) +{ + unsigned buffer_width, buffer_height; + struct sp_mpeg12_context *ctx; + + assert(u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12); + + ctx = CALLOC_STRUCT(sp_mpeg12_context); + + if (!ctx) + return NULL; + + /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */ + assert(pot_buffers); + + buffer_width = pot_buffers ? util_next_power_of_two(width) : width; + buffer_height = pot_buffers ? util_next_power_of_two(height) : height; + + ctx->base.profile = profile; + ctx->base.chroma_format = chroma_format; + ctx->base.width = width; + ctx->base.height = height; + + ctx->base.screen = pipe->screen; + + ctx->base.destroy = sp_mpeg12_destroy; + ctx->base.get_param = sp_mpeg12_get_param; + ctx->base.is_format_supported = sp_mpeg12_is_format_supported; + ctx->base.create_surface = sp_mpeg12_create_surface; + ctx->base.decode_macroblocks = sp_mpeg12_decode_macroblocks; + ctx->base.render_picture = sp_mpeg12_render_picture; + ctx->base.clear_render_target = sp_mpeg12_clear_render_target; + ctx->base.resource_copy_region = sp_mpeg12_resource_copy_region; + ctx->base.get_transfer = sp_mpeg12_get_transfer; + ctx->base.transfer_destroy = sp_mpeg12_transfer_destroy; + ctx->base.transfer_map = sp_mpeg12_transfer_map; + ctx->base.transfer_flush_region = sp_mpeg12_transfer_flush_region; + ctx->base.transfer_unmap = sp_mpeg12_transfer_unmap; + if (pipe->transfer_inline_write) + ctx->base.transfer_inline_write = sp_mpeg12_transfer_inline_write; + ctx->base.set_picture_background = sp_mpeg12_set_picture_background; + ctx->base.set_picture_layers = sp_mpeg12_set_picture_layers; + ctx->base.set_decode_target = sp_mpeg12_set_decode_target; + ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix; + + ctx->pipe = pipe; + ctx->decode_format = decode_format; + + if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe, + buffer_width, buffer_height, chroma_format, + bufmode)) { + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + ctx->buffer_map = util_new_keymap(sizeof(unsigned), -1, delete_buffer); + if (!ctx->buffer_map) { + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) { + util_delete_keymap(ctx->buffer_map, ctx); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + if (!init_pipe_state(ctx)) { + vl_compositor_cleanup(&ctx->compositor); + util_delete_keymap(ctx->buffer_map, ctx); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer); + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; + } + + return &ctx->base; +} + +struct pipe_video_context * +sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv) +{ + struct pipe_context *pipe; + + assert(screen); + assert(width && height); + + pipe = screen->context_create(screen, NULL); + if (!pipe) + return NULL; + + /* TODO: Use slice buffering for softpipe when implemented, no advantage to buffering an entire picture with softpipe */ + return sp_video_create_ex(pipe, profile, + chroma_format, + width, height, + VL_MPEG12_MC_RENDERER_BUFFER_PICTURE, + true, + PIPE_FORMAT_XYUV); +} + +struct pipe_video_context * +sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode, + bool pot_buffers, + enum pipe_format decode_format) +{ + assert(pipe); + assert(width && height); + + switch (u_reduce_video_profile(profile)) { + case PIPE_VIDEO_CODEC_MPEG12: + return sp_mpeg12_create(pipe, profile, + chroma_format, + width, height, + bufmode, + pot_buffers, + decode_format); + default: + return NULL; + } +} diff --git a/src/gallium/drivers/softpipe/sp_video_context.h b/src/gallium/drivers/softpipe/sp_video_context.h new file mode 100644 index 00000000000..9b60bad6b8f --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_video_context.h @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SP_VIDEO_CONTEXT_H +#define SP_VIDEO_CONTEXT_H + +#include <pipe/p_video_context.h> +#include <vl/vl_mpeg12_mc_renderer.h> +#include <vl/vl_compositor.h> + +struct pipe_screen; +struct pipe_context; + +struct sp_mpeg12_context +{ + struct pipe_video_context base; + struct pipe_context *pipe; + struct pipe_surface *decode_target; + struct vl_mpeg12_mc_renderer mc_renderer; + struct keymap *buffer_map; + struct vl_mpeg12_mc_buffer *mc_buffer; + struct vl_compositor compositor; + + void *rast; + void *dsa; + void *blend; + + enum pipe_format decode_format; +}; + +struct pipe_video_context * +sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv); + +/* Other drivers can call this function in their pipe_video_context constructors and pass it + an accelerated pipe_context along with suitable buffering modes, etc */ +struct pipe_video_context * +sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode, + bool pot_buffers, + enum pipe_format decode_format); + +#endif /* SP_VIDEO_CONTEXT_H */ diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index f5af15ff9ff..f60b131f941 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -495,6 +495,32 @@ enum pipe_shader_cap #define PIPE_REFERENCED_FOR_READ (1 << 0) #define PIPE_REFERENCED_FOR_WRITE (1 << 1) +enum pipe_video_codec +{ + PIPE_VIDEO_CODEC_UNKNOWN = 0, + PIPE_VIDEO_CODEC_MPEG12, /**< MPEG1, MPEG2 */ + PIPE_VIDEO_CODEC_MPEG4, /**< DIVX, XVID */ + PIPE_VIDEO_CODEC_VC1, /**< WMV */ + PIPE_VIDEO_CODEC_MPEG4_AVC /**< H.264 */ +}; + +enum pipe_video_profile +{ + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_PROFILE_MPEG1, + PIPE_VIDEO_PROFILE_MPEG2_SIMPLE, + PIPE_VIDEO_PROFILE_MPEG2_MAIN, + PIPE_VIDEO_PROFILE_MPEG4_SIMPLE, + PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE, + PIPE_VIDEO_PROFILE_VC1_SIMPLE, + PIPE_VIDEO_PROFILE_VC1_MAIN, + PIPE_VIDEO_PROFILE_VC1_ADVANCED, + PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE, + PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN, + PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH +}; + + /** * Composite query types */ @@ -509,6 +535,7 @@ struct pipe_query_data_timestamp_disjoint boolean disjoint; }; + #ifdef __cplusplus } #endif diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h index 74a9939df73..3aa11be4b5b 100644 --- a/src/gallium/include/pipe/p_format.h +++ b/src/gallium/include/pipe/p_format.h @@ -186,19 +186,37 @@ enum pipe_format { PIPE_FORMAT_R8G8B8X8_UNORM = 134, PIPE_FORMAT_B4G4R4X4_UNORM = 135, + PIPE_FORMAT_YV12 = 136, + PIPE_FORMAT_YV16 = 137, + PIPE_FORMAT_IYUV = 138, /**< aka I420 */ + PIPE_FORMAT_NV12 = 139, + PIPE_FORMAT_NV21 = 140, + PIPE_FORMAT_AYUV = PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_VUYA = PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_XYUV = PIPE_FORMAT_X8R8G8B8_UNORM, + PIPE_FORMAT_VUYX = PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_FORMAT_IA44 = 141, + PIPE_FORMAT_AI44 = 142, + /* some stencil samplers formats */ - PIPE_FORMAT_X24S8_USCALED = 136, - PIPE_FORMAT_S8X24_USCALED = 137, - PIPE_FORMAT_X32_S8X24_USCALED = 138, + PIPE_FORMAT_X24S8_USCALED = 143, + PIPE_FORMAT_S8X24_USCALED = 144, + PIPE_FORMAT_X32_S8X24_USCALED = 145, - PIPE_FORMAT_B2G3R3_UNORM = 139, - PIPE_FORMAT_L16A16_UNORM = 140, - PIPE_FORMAT_A16_UNORM = 141, - PIPE_FORMAT_I16_UNORM = 142, + PIPE_FORMAT_B2G3R3_UNORM = 146, + PIPE_FORMAT_L16A16_UNORM = 147, + PIPE_FORMAT_A16_UNORM = 148, + PIPE_FORMAT_I16_UNORM = 149, PIPE_FORMAT_COUNT }; +enum pipe_video_chroma_format +{ + PIPE_VIDEO_CHROMA_FORMAT_420, + PIPE_VIDEO_CHROMA_FORMAT_422, + PIPE_VIDEO_CHROMA_FORMAT_444 +}; #ifdef __cplusplus } diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index 850eb84a3c8..2a6acecb726 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -92,8 +92,13 @@ struct pipe_screen { */ int (*get_shader_param)( struct pipe_screen *, unsigned shader, enum pipe_shader_cap param ); - struct pipe_context * (*context_create)( struct pipe_screen *, - void *priv ); + struct pipe_context * (*context_create)( struct pipe_screen *, void *priv ); + + struct pipe_video_context * (*video_context_create)( struct pipe_screen *screen, + enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, void *priv ); + /** * Check if the given pipe_format is supported as a texture or diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h new file mode 100644 index 00000000000..73f03d58ea6 --- /dev/null +++ b/src/gallium/include/pipe/p_video_context.h @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef PIPE_VIDEO_CONTEXT_H +#define PIPE_VIDEO_CONTEXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <pipe/p_video_state.h> + +/* XXX: Move to an appropriate place */ +#define PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT 256 + +struct pipe_screen; +struct pipe_buffer; +struct pipe_surface; +struct pipe_macroblock; +struct pipe_picture_desc; +struct pipe_fence_handle; + +/** + * Gallium video rendering context + */ +struct pipe_video_context +{ + struct pipe_screen *screen; + enum pipe_video_profile profile; + enum pipe_video_chroma_format chroma_format; + unsigned width; + unsigned height; + + void *priv; /**< context private data (for DRI for example) */ + + /** + * Query an integer-valued capability/parameter/limit + * \param param one of PIPE_CAP_x + */ + int (*get_param)(struct pipe_video_context *vpipe, int param); + + /** + * Check if the given pipe_format is supported as a texture or + * drawing surface. + */ + boolean (*is_format_supported)(struct pipe_video_context *vpipe, + enum pipe_format format, + unsigned usage, + unsigned geom); + + void (*destroy)(struct pipe_video_context *vpipe); + + struct pipe_surface *(*create_surface)(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + const struct pipe_surface *templat); + + /** + * Picture decoding and displaying + */ + /*@{*/ + void (*decode_bitstream)(struct pipe_video_context *vpipe, + unsigned num_bufs, + struct pipe_buffer **bitstream_buf); + + void (*decode_macroblocks)(struct pipe_video_context *vpipe, + struct pipe_surface *past, + struct pipe_surface *future, + unsigned num_macroblocks, + struct pipe_macroblock *macroblocks, + struct pipe_fence_handle **fence); + + void (*render_picture)(struct pipe_video_context *vpipe, + struct pipe_surface *src_surface, + enum pipe_mpeg12_picture_type picture_type, + /*unsigned num_past_surfaces, + struct pipe_surface *past_surfaces, + unsigned num_future_surfaces, + struct pipe_surface *future_surfaces,*/ + struct pipe_video_rect *src_area, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence); + + void (*clear_render_target)(struct pipe_video_context *vpipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + const float *rgba, + unsigned width, unsigned height); + + void (*resource_copy_region)(struct pipe_video_context *vpipe, + struct pipe_resource *dst, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned srcx, unsigned srcy, unsigned srcz, + unsigned width, unsigned height); + + struct pipe_transfer *(*get_transfer)(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ + const struct pipe_box *box); + + void (*transfer_destroy)(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer); + + void* (*transfer_map)(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer); + + void (*transfer_flush_region)(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer, + const struct pipe_box *box); + + void (*transfer_unmap)(struct pipe_video_context *vpipe, + struct pipe_transfer *transfer); + + void (*transfer_inline_write)(struct pipe_video_context *vpipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned slice_stride); + + /*@}*/ + + /** + * Parameter-like states (or properties) + */ + /*@{*/ + void (*set_picture_background)(struct pipe_video_context *vpipe, + struct pipe_surface *bg, + struct pipe_video_rect *bg_src_rect); + + void (*set_picture_layers)(struct pipe_video_context *vpipe, + struct pipe_surface *layers[], + struct pipe_video_rect *src_rects[], + struct pipe_video_rect *dst_rects[], + unsigned num_layers); + + void (*set_picture_desc)(struct pipe_video_context *vpipe, + const struct pipe_picture_desc *desc); + + void (*set_decode_target)(struct pipe_video_context *vpipe, + struct pipe_surface *dt); + + void (*set_csc_matrix)(struct pipe_video_context *vpipe, const float *mat); + + /* TODO: Interface for scaling modes, post-processing, etc. */ + /*@}*/ +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* PIPE_VIDEO_CONTEXT_H */ diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h new file mode 100644 index 00000000000..1cb555b5381 --- /dev/null +++ b/src/gallium/include/pipe/p_video_state.h @@ -0,0 +1,134 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef PIPE_VIDEO_STATE_H +#define PIPE_VIDEO_STATE_H + +#include <pipe/p_defines.h> +#include <pipe/p_format.h> +#include <pipe/p_state.h> +#include <pipe/p_screen.h> +#include <util/u_inlines.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_video_rect +{ + unsigned x, y, w, h; +}; + +enum pipe_mpeg12_picture_type +{ + PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP, + PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM, + PIPE_MPEG12_PICTURE_TYPE_FRAME +}; + +enum pipe_mpeg12_macroblock_type +{ + PIPE_MPEG12_MACROBLOCK_TYPE_INTRA, + PIPE_MPEG12_MACROBLOCK_TYPE_FWD, + PIPE_MPEG12_MACROBLOCK_TYPE_BKWD, + PIPE_MPEG12_MACROBLOCK_TYPE_BI, + + PIPE_MPEG12_MACROBLOCK_NUM_TYPES +}; + +enum pipe_mpeg12_motion_type +{ + PIPE_MPEG12_MOTION_TYPE_FIELD, + PIPE_MPEG12_MOTION_TYPE_FRAME, + PIPE_MPEG12_MOTION_TYPE_DUALPRIME, + PIPE_MPEG12_MOTION_TYPE_16x8 +}; + +enum pipe_mpeg12_dct_type +{ + PIPE_MPEG12_DCT_TYPE_FIELD, + PIPE_MPEG12_DCT_TYPE_FRAME +}; + + +struct pipe_macroblock +{ + enum pipe_video_codec codec; +}; + +struct pipe_mpeg12_macroblock +{ + struct pipe_macroblock base; + + unsigned mbx; + unsigned mby; + enum pipe_mpeg12_macroblock_type mb_type; + enum pipe_mpeg12_motion_type mo_type; + enum pipe_mpeg12_dct_type dct_type; + signed pmv[2][2][2]; + bool mvfs[2][2]; + unsigned cbp; + short *blocks; +}; + +#if 0 +struct pipe_picture_desc +{ + enum pipe_video_format format; +}; + +struct pipe_mpeg12_picture_desc +{ + struct pipe_picture_desc base; + + /* TODO: Use bitfields where possible? */ + struct pipe_surface *forward_reference; + struct pipe_surface *backward_reference; + unsigned picture_coding_type; + unsigned fcode; + unsigned intra_dc_precision; + unsigned picture_structure; + unsigned top_field_first; + unsigned frame_pred_frame_dct; + unsigned concealment_motion_vectors; + unsigned q_scale_type; + unsigned intra_vlc_format; + unsigned alternate_scan; + unsigned full_pel_forward_vector; + unsigned full_pel_backward_vector; + struct pipe_buffer *intra_quantizer_matrix; + struct pipe_buffer *non_intra_quantizer_matrix; + struct pipe_buffer *chroma_intra_quantizer_matrix; + struct pipe_buffer *chroma_non_intra_quantizer_matrix; +}; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PIPE_VIDEO_STATE_H */ diff --git a/src/gallium/state_trackers/va/Makefile b/src/gallium/state_trackers/va/Makefile new file mode 100644 index 00000000000..dd303ebace9 --- /dev/null +++ b/src/gallium/state_trackers/va/Makefile @@ -0,0 +1,28 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = vatracker + +VA_MAJOR = 0 +VA_MINOR = 3 +LIBRARY_DEFINES = -DVER_MAJOR=$(VA_MAJOR) -DVER_MINOR=$(VA_MINOR) $(STATE_TRACKER_DEFINES) + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I va) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = htab.c \ + ftab.c \ + va_context.c \ + va_image.c \ + va_subpicture.c \ + va_buffer.c \ + va_config.c \ + va_picture.c \ + va_surface.c \ + va_display.c + + + +include ../../Makefile.template + diff --git a/src/gallium/state_trackers/va/ftab.c b/src/gallium/state_trackers/va/ftab.c new file mode 100644 index 00000000000..999287e7a7e --- /dev/null +++ b/src/gallium/state_trackers/va/ftab.c @@ -0,0 +1,136 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <va/va.h> +#include <va/va_backend.h> +#include "va_private.h" + +struct VADriverVTable vlVaGetVtable(); + +static struct VADriverVTable vtable = +{ + &vlVaTerminate, /* VAStatus (*vaTerminate) ( VADriverContextP ctx ); */ + &vlVaQueryConfigProfiles, /* VAStatus (*vaQueryConfigProfiles) ( VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); */ + &vlVaQueryConfigEntrypoints, /* VAStatus (*vaQueryConfigEntrypoints) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints ); */ + &vlVaGetConfigAttributes, /* VAStatus (*vaGetConfigAttributes) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs ); */ + &vlVaCreateConfig, /* VAStatus (*vaCreateConfig) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); */ + &vlVaDestroyConfig, /* VAStatus (*vaDestroyConfig) ( VADriverContextP ctx, VAConfigID config_id); */ + &vlVaQueryConfigAttributes, /* VAStatus (*vaQueryConfigAttributes) ( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); */ + &vlVaCreateSurfaces, /* VAStatus (*vaCreateSurfaces) ( VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID *surfaces); */ + &vlVaDestroySurfaces, /* VAStatus (*vaDestroySurfaces) ( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ); */ + &vlVaCreateContext, /* VAStatus (*vaCreateContext) (VADriverContextP ctx,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID *render_targets,int num_render_targets,VAContextID *context); */ + &vlVaDestroyContext, /* VAStatus (*vaDestroyContext) (VADriverContextP ctx,VAContextID context); */ + &vlVaCreateBuffer, /* VAStatus (*vaCreateBuffer) (VADriverContextP ctx,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void *data,VABufferID *buf_id); */ + &vlVaBufferSetNumElements, /* VAStatus (*vaBufferSetNumElements) (VADriverContextP ctx,VABufferID buf_id,unsigned int num_elements); */ + &vlVaMapBuffer, /* VAStatus (*vaMapBuffer) (VADriverContextP ctx,VABufferID buf_id,void **pbuf); */ + &vlVaUnmapBuffer, /* VAStatus (*vaUnmapBuffer) (VADriverContextP ctx,VABufferID buf_id); */ + &vlVaDestroyBuffer, /* VAStatus (*vaDestroyBuffer) (VADriverContextP ctx,VABufferID buffer_id); */ + &vlVaBeginPicture, /* VAStatus (*vaBeginPicture) (VADriverContextP ctx,VAContextID context,VASurfaceID render_target); */ + &vlVaRenderPicture, /* VAStatus (*vaRenderPicture) (VADriverContextP ctx,VAContextID context,VABufferID *buffers,int num_buffers); */ + &vlVaEndPicture, /* VAStatus (*vaEndPicture) (VADriverContextP ctx,VAContextID context); */ + &vlVaSyncSurface, /* VAStatus (*vaSyncSurface) (VADriverContextP ctx,VASurfaceID render_target); */ + &vlVaQuerySurfaceStatus, /* VAStatus (*vaQuerySurfaceStatus) (VADriverContextP ctx,VASurfaceID render_target,VASurfaceStatus *status); */ + &vlVaPutSurface, /* VAStatus (*vaPutSurface) ( + VADriverContextP ctx, + VASurfaceID surface, + void* draw, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, + unsigned int number_cliprects, + unsigned int flags); */ + &vlVaQueryImageFormats, /* VAStatus (*vaQueryImageFormats) ( VADriverContextP ctx, VAImageFormat *format_list,int *num_formats); */ + &vlVaCreateImage, /* VAStatus (*vaCreateImage) (VADriverContextP ctx,VAImageFormat *format,int width,int height,VAImage *image); */ + &vlVaDeriveImage, /* VAStatus (*vaDeriveImage) (VADriverContextP ctx,VASurfaceID surface,VAImage *image); */ + &vlVaDestroyImage, /* VAStatus (*vaDestroyImage) (VADriverContextP ctx,VAImageID image); */ + &vlVaSetImagePalette, /* VAStatus (*vaSetImagePalette) (VADriverContextP ctx,VAImageID image, unsigned char *palette); */ + &vlVaGetImage, /* VAStatus (*vaGetImage) (VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image); */ + &vlVaPutImage, /* VAStatus (*vaPutImage) ( + VADriverContextP ctx, + VASurfaceID surface, + VAImageID image, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y, + unsigned int dest_width, + unsigned int dest_height + ); */ + &vlVaQuerySubpictureFormats, /* VAStatus (*vaQuerySubpictureFormats) (VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); */ + &vlVaCreateSubpicture, /* VAStatus (*vaCreateSubpicture) (VADriverContextP ctx,VAImageID image,VASubpictureID *subpicture); */ + &vlVaDestroySubpicture, /* VAStatus (*vaDestroySubpicture) (VADriverContextP ctx,VASubpictureID subpicture); */ + &vlVaSubpictureImage, /* VAStatus (*vaSetSubpictureImage) (VADriverContextP ctx,VASubpictureID subpicture,VAImageID image); */ + &vlVaSetSubpictureChromakey, /* VAStatus (*vaSetSubpictureChromakey) (VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask); */ + &vlVaSetSubpictureGlobalAlpha, /* VAStatus (*vaSetSubpictureGlobalAlpha) (VADriverContextP ctx,VASubpictureID subpicture,float global_alpha); */ + &vlVaAssociateSubpicture, /* VAStatus (*vaAssociateSubpicture) ( + VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces, + short src_x, + short src_y, + unsigned short src_width, + unsigned short src_height, + short dest_x, + short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags); */ + &vlVaDeassociateSubpicture, /* VAStatus (*vaDeassociateSubpicture) (VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID *target_surfaces,int num_surfaces); */ + &vlVaQueryDisplayAttributes, /* VAStatus (*vaQueryDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int *num_attributes); */ + &vlVaGetDisplayAttributes, /* VAStatus (*vaGetDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); */ + &vlVaSetDisplayAttributes, /* VAStatus (*vaSetDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); */ + &vlVaBufferInfo, /* VAStatus (*vaBufferInfo) (VADriverContextP ctx,VAContextID context,VABufferID buf_id,VABufferType *type,unsigned int *size,unsigned int *num_elements); */ + &vlVaLockSurface, /* VAStatus (*vaLockSurface) ( + VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *luma_stride, + unsigned int *chroma_u_stride, + unsigned int *chroma_v_stride, + unsigned int *luma_offset, + unsigned int *chroma_u_offset, + unsigned int *chroma_v_offset, + unsigned int *buffer_name, + void **buffer); */ + &vlVaUnlockSurface, /* VAStatus (*vaUnlockSurface) (VADriverContextP ctx,VASurfaceID surface); */ + NULL /* struct VADriverVTableGLX *glx; "Optional" */ +}; + +struct VADriverVTable vlVaGetVtable() +{ + return vtable; +} diff --git a/src/gallium/state_trackers/va/htab.c b/src/gallium/state_trackers/va/htab.c new file mode 100644 index 00000000000..2187507c6a4 --- /dev/null +++ b/src/gallium/state_trackers/va/htab.c @@ -0,0 +1,99 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_handle_table.h> +#include <os/os_thread.h> +#include "va_private.h" + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); + +#ifdef VL_HANDLES +static struct handle_table *htab = NULL; +pipe_static_mutex(htab_lock); +#endif + +boolean vlCreateHTAB(void) +{ +#ifdef VL_HANDLES + boolean ret; + /* Make sure handle table handles match VDPAU handles. */ + assert(sizeof(unsigned) <= sizeof(vlHandle)); + pipe_mutex_lock(htab_lock); + if (!htab) + htab = handle_table_create(); + ret = htab != NULL; + pipe_mutex_unlock(htab_lock); + return ret; +#else + return TRUE; +#endif +} + +void vlDestroyHTAB(void) +{ +#ifdef VL_HANDLES + pipe_mutex_lock(htab_lock); + if (htab) { + handle_table_destroy(htab); + htab = NULL; + } + pipe_mutex_unlock(htab_lock); +#endif +} + +vlHandle vlAddDataHTAB(void *data) +{ + assert(data); +#ifdef VL_HANDLES + vlHandle handle = 0; + pipe_mutex_lock(htab_lock); + if (htab) + handle = handle_table_add(htab, data); + pipe_mutex_unlock(htab_lock); + return handle; +#else + return (vlHandle)data; +#endif +} + +void* vlGetDataHTAB(vlHandle handle) +{ + assert(handle); +#ifdef VL_HANDLES + void *data = NULL; + pipe_mutex_lock(htab_lock); + if (htab) + data = handle_table_get(htab, handle); + pipe_mutex_unlock(htab_lock); + return data; +#else + return (void*)handle; +#endif +} diff --git a/src/gallium/state_trackers/va/va_buffer.c b/src/gallium/state_trackers/va/va_buffer.c new file mode 100644 index 00000000000..7608a4264ff --- /dev/null +++ b/src/gallium/state_trackers/va/va_buffer.c @@ -0,0 +1,96 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include "va_private.h" + + +VAStatus vlVaCreateBuffer( VADriverContextP ctx, + VAContextID context, + VABufferType type, + unsigned int size, + unsigned int num_elements, + void *data, + VABufferID *buf_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaBufferSetNumElements( VADriverContextP ctx, + VABufferID buf_id, + unsigned int num_elements) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaMapBuffer( VADriverContextP ctx, + VABufferID buf_id, + void **pbuff) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaUnmapBuffer( VADriverContextP ctx, + VABufferID buf_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDestroyBuffer( VADriverContextP ctx, + VABufferID buffer_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaBufferInfo( VADriverContextP ctx, + VAContextID context, + VABufferID buf_id, + VABufferType *type, + unsigned int *size, + unsigned int *num_elements) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_config.c b/src/gallium/state_trackers/va/va_config.c new file mode 100644 index 00000000000..1589abf7cfa --- /dev/null +++ b/src/gallium/state_trackers/va/va_config.c @@ -0,0 +1,131 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include <util/u_debug.h> +#include "va_private.h" + +VAStatus vlVaQueryConfigProfiles( VADriverContextP ctx, + VAProfile *profile_list, + int *num_profiles) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + int i = 0; + + profile_list[i++] = VAProfileMPEG2Simple; + *num_profiles = i; + + return VA_STATUS_SUCCESS; +} + + +VAStatus vlVaQueryConfigEntrypoints( VADriverContextP ctx, + VAProfile profile, + VAEntrypoint *entrypoint_list, + int *num_entrypoints) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + VAStatus vaStatus = VA_STATUS_SUCCESS; + + switch (profile) { + case VAProfileMPEG2Simple: + case VAProfileMPEG2Main: + VA_INFO("Using profile %08x\n",profile); + *num_entrypoints = 1; + entrypoint_list[0] = VAEntrypointMoComp; + break; + + case VAProfileH264Baseline: + case VAProfileH264Main: + case VAProfileH264High: + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + *num_entrypoints = 0; + break; + + default: + VA_ERROR("Unsupported profile %08x\n",profile); + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + *num_entrypoints = 0; + break; + } + + return vaStatus; +} + + +VAStatus vlVaGetConfigAttributes( VADriverContextP ctx, + VAProfile profile, + VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, + int num_attribs) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaCreateConfig( VADriverContextP ctx, + VAProfile profile, + VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, + int num_attribs, + VAConfigID *config_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDestroyConfig( VADriverContextP ctx, + VAConfigID config_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaQueryConfigAttributes( VADriverContextP ctx, + VAConfigID config_id, + VAProfile *profile, + VAEntrypoint *entrypoint, + VAConfigAttrib *attrib_list, + int *num_attribs) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + diff --git a/src/gallium/state_trackers/va/va_context.c b/src/gallium/state_trackers/va/va_context.c new file mode 100644 index 00000000000..cdb20cc0eb2 --- /dev/null +++ b/src/gallium/state_trackers/va/va_context.c @@ -0,0 +1,107 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <pipe/p_compiler.h> +#include <pipe/p_video_context.h> +#include <pipe/p_screen.h> +#include <vl_winsys.h> +#include <util/u_debug.h> +#include <util/u_memory.h> +#include <va/va.h> +#include <va/va_backend.h> +#include "va_private.h" + +//struct VADriverVTable vlVaGetVtable(); + +PUBLIC +VAStatus __vaDriverInit_0_31 (VADriverContextP ctx) +{ + vlVaDriverContextPriv *driver_context = NULL; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + /* Create private driver context */ + driver_context = CALLOC(1,sizeof(vlVaDriverContextPriv)); + if (!driver_context) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + driver_context->vscreen = vl_screen_create(ctx->native_dpy, ctx->x11_screen); + if (!driver_context->vscreen) + { + FREE(driver_context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + ctx->str_vendor = "mesa gallium vaapi"; + ctx->vtable = vlVaGetVtable(); + ctx->max_attributes = 1; + ctx->max_display_attributes = 1; + ctx->max_entrypoints = VA_MAX_ENTRYPOINTS; + ctx->max_image_formats = VA_MAX_IMAGE_FORMATS_SUPPORTED; + ctx->max_profiles = 1; + ctx->max_subpic_formats = VA_MAX_SUBPIC_FORMATS_SUPPORTED; + ctx->version_major = 3; + ctx->version_minor = 1; + ctx->pDriverData = (void *)driver_context; + + VA_INFO("vl_screen_pointer %p\n",ctx->native_dpy); + + return VA_STATUS_SUCCESS; +} + +VAStatus vlVaCreateContext( VADriverContextP ctx, + VAConfigID config_id, + int picture_width, + int picture_height, + int flag, + VASurfaceID *render_targets, + int num_render_targets, + VAContextID *conext) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDestroyContext( VADriverContextP ctx, + VAContextID context) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaTerminate( VADriverContextP ctx) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/tests/unit/pipe_barrier_test.c b/src/gallium/state_trackers/va/va_display.c index f5d72b0abae..1aaaf7ccc53 100644 --- a/src/gallium/tests/unit/pipe_barrier_test.c +++ b/src/gallium/state_trackers/va/va_display.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2009-2010 VMware, Inc. + * Copyright 2010 Thomas Balling Sørensen. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,69 +18,53 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ + #include <va/va.h> + #include <va/va_backend.h> + #include "va_private.h" -/* - * Test case for pipe_barrier. - * - * The test succeeds if no thread exits before all the other threads reach - * the barrier. - */ - - -#include <stdio.h> - -#include "os/os_thread.h" -#include "os/os_time.h" +VAStatus vlVaQueryDisplayAttributes( VADriverContextP ctx, + VADisplayAttribute *attr_list, + int *num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; -#define NUM_THREADS 10 + if (!(attr_list && num_attributes)) + return VA_STATUS_ERROR_UNKNOWN; -static pipe_thread threads[NUM_THREADS]; -static pipe_barrier barrier; -static int thread_ids[NUM_THREADS]; + *num_attributes = 0; + return VA_STATUS_SUCCESS; +} -static PIPE_THREAD_ROUTINE(thread_function, thread_data) +VAStatus vlVaGetDisplayAttributes( VADriverContextP ctx, + VADisplayAttribute *attr_list, + int num_attributes) { - int thread_id = *((int *) thread_data); + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; - printf("thread %d starting\n", thread_id); - os_time_sleep(thread_id * 1000 * 1000); - printf("thread %d before barrier\n", thread_id); - pipe_barrier_wait(&barrier); - printf("thread %d exiting\n", thread_id); - return NULL; + return VA_STATUS_ERROR_UNIMPLEMENTED; } - -int main() +VAStatus vlVaSetDisplayAttributes( VADriverContextP ctx, + VADisplayAttribute *attr_list, + int num_attributes) { - int i; - - printf("pipe_barrier_test starting\n"); - - pipe_barrier_init(&barrier, NUM_THREADS); + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; - for (i = 0; i < NUM_THREADS; i++) { - thread_ids[i] = i; - threads[i] = pipe_thread_create(thread_function, (void *) &thread_ids[i]); - } - for (i = 0; i < NUM_THREADS; i++ ) { - pipe_thread_wait(threads[i]); - } - - pipe_barrier_destroy(&barrier); + return VA_STATUS_ERROR_UNIMPLEMENTED; +} - printf("pipe_barrier_test exiting\n"); - return 0; -} diff --git a/src/gallium/state_trackers/va/va_image.c b/src/gallium/state_trackers/va/va_image.c new file mode 100644 index 00000000000..8d20bfa9174 --- /dev/null +++ b/src/gallium/state_trackers/va/va_image.c @@ -0,0 +1,178 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_memory.h> +#include <util/u_format.h> +#include <util/u_debug.h> +#include <pipe/p_format.h> +#include <va/va.h> +#include <va/va_backend.h> +#include "va_private.h" + +typedef struct { + enum pipe_format pipe_format; + VAImageFormat va_format; +} va_image_formats_supported_t; + +static const va_image_formats_supported_t va_image_formats_supported[VA_MAX_IMAGE_FORMATS_SUPPORTED] = +{ + { PIPE_FORMAT_B8G8R8A8_UNORM, + { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }}, + { PIPE_FORMAT_R8G8B8A8_UNORM, + { VA_FOURCC_RGBA, VA_LSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }} +}; + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); + +VAStatus +vlVaQueryImageFormats ( VADriverContextP ctx, + VAImageFormat *format_list, + int *num_formats) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && num_formats)) + return VA_STATUS_ERROR_UNKNOWN; + + int n = 0; + + num_formats[0] = VA_MAX_IMAGE_FORMATS_SUPPORTED; + + /* Query supported formats */ + for (n = 0; n < VA_MAX_IMAGE_FORMATS_SUPPORTED; n++) + { + format_list[n] = va_image_formats_supported[n].va_format; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus vlVaCreateImage( VADriverContextP ctx, + VAImageFormat *format, + int width, + int height, + VAImage *image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if(!format) + return VA_STATUS_ERROR_UNKNOWN; + + if (!(width && height)) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + if (!vlCreateHTAB()) + return VA_STATUS_ERROR_UNKNOWN; + + switch (format->fourcc) { + case VA_FOURCC('B','G','R','A'): + VA_INFO("Creating BGRA image of size %dx%d\n",width,height); + break; + case VA_FOURCC_RGBA: + VA_INFO("Creating RGBA image of size %dx%d\n",width,height); + break; + default: + VA_ERROR("Couldn't create image of type %0x08\n",format->fourcc); + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + break; + } + + VA_INFO("Image %p created successfully\n",format); + + return VA_STATUS_SUCCESS; +} + +VAStatus vlVaDeriveImage( VADriverContextP ctx, + VASurfaceID surface, + VAImage *image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDestroyImage( VADriverContextP ctx, + VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaSetImagePalette( VADriverContextP ctx, + VAImageID image, + unsigned char *palette) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaGetImage( VADriverContextP ctx, + VASurfaceID surface, + int x, + int y, + unsigned int width, + unsigned int height, + VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaPutImage( VADriverContextP ctx, + VASurfaceID surface, + VAImageID image, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y, + unsigned int dest_width, + unsigned int dest_height) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_picture.c b/src/gallium/state_trackers/va/va_picture.c new file mode 100644 index 00000000000..3603dfb6fed --- /dev/null +++ b/src/gallium/state_trackers/va/va_picture.c @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include <util/u_debug.h> +#include "va_private.h" + +VAStatus vlVaBeginPicture( VADriverContextP ctx, + VAContextID context, + VASurfaceID render_target) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaRenderPicture( VADriverContextP ctx, + VAContextID context, + VABufferID *buffers, + int num_buffers) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaEndPicture( VADriverContextP ctx, + VAContextID context) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h new file mode 100644 index 00000000000..625c6cdbe1b --- /dev/null +++ b/src/gallium/state_trackers/va/va_private.h @@ -0,0 +1,159 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VA_PRIVATE_H +#define VA_PRIVATE_H + +#include <va/va.h> +#include <va/va_backend.h> +#include <pipe/p_format.h> +#include <pipe/p_state.h> + +#define VA_DEBUG(_str,...) debug_printf("[Gallium VA backend]: " _str,__VA_ARGS__) +#define VA_INFO(_str,...) VA_DEBUG("INFO: " _str,__VA_ARGS__) +#define VA_WARNING(_str,...) VA_DEBUG("WARNING: " _str,__VA_ARGS__) +#define VA_ERROR(_str,...) VA_DEBUG("ERROR: " _str,__VA_ARGS__) + +#define VA_MAX_IMAGE_FORMATS_SUPPORTED 2 +#define VA_MAX_SUBPIC_FORMATS_SUPPORTED 2 +#define VA_MAX_ENTRYPOINTS 1 + +#define VL_HANDLES + +typedef unsigned int vlHandle; + +typedef struct { + struct vl_screen *vscreen; + struct pipe_surface *backbuffer; +} vlVaDriverContextPriv; + +typedef struct { + unsigned int width; + unsigned int height; + enum pipe_video_chroma_format format; + VADriverContextP ctx; +} vlVaSurfacePriv; + +// Public functions: +VAStatus __vaDriverInit_0_31 (VADriverContextP ctx); + +// Private functions: +struct VADriverVTable vlVaGetVtable(); + + +// Vtable functions: +VAStatus vlVaTerminate (VADriverContextP ctx); +VAStatus vlVaQueryConfigProfiles (VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); +VAStatus vlVaQueryConfigEntrypoints (VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints); +VAStatus vlVaGetConfigAttributes (VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs); +VAStatus vlVaCreateConfig (VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); +VAStatus vlVaDestroyConfig (VADriverContextP ctx, VAConfigID config_id); +VAStatus vlVaQueryConfigAttributes (VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); +VAStatus vlVaCreateSurfaces (VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID *surfaces); +VAStatus vlVaDestroySurfaces (VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces); +VAStatus vlVaCreateContext (VADriverContextP ctx,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID *render_targets,int num_render_targets,VAContextID *context); +VAStatus vlVaDestroyContext (VADriverContextP ctx,VAContextID context); +VAStatus vlVaCreateBuffer (VADriverContextP ctx,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void *data,VABufferID *buf_id); +VAStatus vlVaBufferSetNumElements (VADriverContextP ctx,VABufferID buf_id,unsigned int num_elements); +VAStatus vlVaMapBuffer (VADriverContextP ctx,VABufferID buf_id,void **pbuf); +VAStatus vlVaUnmapBuffer (VADriverContextP ctx,VABufferID buf_id); +VAStatus vlVaDestroyBuffer (VADriverContextP ctx,VABufferID buffer_id); +VAStatus vlVaBeginPicture (VADriverContextP ctx,VAContextID context,VASurfaceID render_target); +VAStatus vlVaRenderPicture (VADriverContextP ctx,VAContextID context,VABufferID *buffers,int num_buffers); +VAStatus vlVaEndPicture (VADriverContextP ctx,VAContextID context); +VAStatus vlVaSyncSurface (VADriverContextP ctx,VASurfaceID render_target); +VAStatus vlVaQuerySurfaceStatus (VADriverContextP ctx,VASurfaceID render_target,VASurfaceStatus *status); +VAStatus vlVaPutSurface (VADriverContextP ctx, + VASurfaceID surface, + void* draw, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, + unsigned int number_cliprects, + unsigned int flags); +VAStatus vlVaQueryImageFormats (VADriverContextP ctx,VAImageFormat *format_list,int *num_formats); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); +VAStatus vlVaCreateImage(VADriverContextP ctx,VAImageFormat *format,int width,int height,VAImage *image); +VAStatus vlVaDeriveImage(VADriverContextP ctx,VASurfaceID surface,VAImage *image); +VAStatus vlVaDestroyImage(VADriverContextP ctx,VAImageID image); +VAStatus vlVaSetImagePalette(VADriverContextP ctx,VAImageID image, unsigned char *palette); +VAStatus vlVaGetImage(VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image); +VAStatus vlVaPutImage(VADriverContextP ctx, + VASurfaceID surface, + VAImageID image, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y, + unsigned int dest_width, + unsigned int dest_height); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); +VAStatus vlVaCreateSubpicture(VADriverContextP ctx,VAImageID image,VASubpictureID *subpicture); +VAStatus vlVaDestroySubpicture(VADriverContextP ctx,VASubpictureID subpicture); +VAStatus vlVaSubpictureImage(VADriverContextP ctx,VASubpictureID subpicture,VAImageID image); +VAStatus vlVaSetSubpictureChromakey(VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask); +VAStatus vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx,VASubpictureID subpicture,float global_alpha); +VAStatus vlVaAssociateSubpicture(VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces, + short src_x, + short src_y, + unsigned short src_width, + unsigned short src_height, + short dest_x, + short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags); +VAStatus vlVaDeassociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID *target_surfaces,int num_surfaces); +VAStatus vlVaQueryDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int *num_attributes); +VAStatus vlVaGetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); +VAStatus vlVaSetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); +VAStatus vlVaBufferInfo(VADriverContextP ctx,VAContextID context,VABufferID buf_id,VABufferType *type,unsigned int *size,unsigned int *num_elements); +VAStatus vlVaLockSurface(VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *luma_stride, + unsigned int *chroma_u_stride, + unsigned int *chroma_v_stride, + unsigned int *luma_offset, + unsigned int *chroma_u_offset, + unsigned int *chroma_v_offset, + unsigned int *buffer_name, + void **buffer); +VAStatus vlVaUnlockSurface(VADriverContextP ctx,VASurfaceID surface); + +#endif //VA_PRIVATE_H diff --git a/src/gallium/state_trackers/va/va_subpicture.c b/src/gallium/state_trackers/va/va_subpicture.c new file mode 100644 index 00000000000..910e5bd7b70 --- /dev/null +++ b/src/gallium/state_trackers/va/va_subpicture.c @@ -0,0 +1,157 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include <pipe/p_format.h> +#include "va_private.h" + + +typedef struct { + enum pipe_format pipe_format; + VAImageFormat va_format; + unsigned int va_flags; +} va_subpicture_formats_supported_t; + +static const va_subpicture_formats_supported_t va_subpicture_formats_supported[VA_MAX_SUBPIC_FORMATS_SUPPORTED + 1] = +{ + { PIPE_FORMAT_B8G8R8A8_UNORM, + { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + 0 }, + { PIPE_FORMAT_R8G8B8A8_UNORM, + { VA_FOURCC_RGBA, VA_LSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, + 0 } +}; + +VAStatus +vlVaQuerySubpictureFormats( VADriverContextP ctx, + VAImageFormat *format_list, + unsigned int *flags, + unsigned int *num_formats) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && flags && num_formats)) + return VA_STATUS_ERROR_UNKNOWN; + + num_formats[0] = VA_MAX_SUBPIC_FORMATS_SUPPORTED; + + int n = 0; + /* Query supported formats */ + for (n = 0; n < VA_MAX_SUBPIC_FORMATS_SUPPORTED ; n++) + { + const va_subpicture_formats_supported_t * const format_map = &va_subpicture_formats_supported[n]; + flags[n] = format_map->va_flags; + format_list[n] = format_map->va_format; + } + + return VA_STATUS_SUCCESS; +} + + +VAStatus vlVaCreateSubpicture( VADriverContextP ctx, + VAImageID image, + VASubpictureID *subpicture) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDestroySubpicture( VADriverContextP ctx, + VASubpictureID subpicture) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaSubpictureImage( VADriverContextP ctx, + VASubpictureID subpicture, + VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaSetSubpictureChromakey( VADriverContextP ctx, + VASubpictureID subpicture, + unsigned int chromakey_min, + unsigned int chromakey_max, + unsigned int chromakey_mask) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaSetSubpictureGlobalAlpha( VADriverContextP ctx, + VASubpictureID subpicture, + float global_alpha) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaAssociateSubpicture( VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces, + short src_x, + short src_y, + unsigned short src_width, + unsigned short src_height, + short dest_x, + short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaDeassociateSubpicture( VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_surface.c b/src/gallium/state_trackers/va/va_surface.c new file mode 100644 index 00000000000..a86c806248a --- /dev/null +++ b/src/gallium/state_trackers/va/va_surface.c @@ -0,0 +1,167 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include <util/u_debug.h> +#include <util/u_memory.h> +#include "va_private.h" + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); + +static enum pipe_video_chroma_format VaRTFormatToPipe(unsigned int va_type) +{ + switch (va_type) { + case VA_RT_FORMAT_YUV420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VA_RT_FORMAT_YUV422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VA_RT_FORMAT_YUV444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return -1; +} + +VAStatus vlVaCreateSurfaces( VADriverContextP ctx, + int width, + int height, + int format, + int num_surfaces, + VASurfaceID *surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + /* We only support one format */ + if (VA_RT_FORMAT_YUV420 != format) + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + + if (!(width && height)) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + if (!vlCreateHTAB()) + return VA_STATUS_ERROR_UNKNOWN; + + vlVaSurfacePriv *va_surface = (vlVaSurfacePriv *)CALLOC(num_surfaces,sizeof(vlVaSurfacePriv)); + if (!va_surface) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + int n = 0; + for (n = 0; n < num_surfaces; n++) + { + va_surface[n].width = width; + va_surface[n].height = height; + va_surface[n].format = VaRTFormatToPipe(format); + va_surface[n].ctx = ctx; + surfaces[n] = (VASurfaceID *)vlAddDataHTAB((void *)(va_surface + n)); + } + + return VA_STATUS_SUCCESS; +} + +VAStatus vlVaDestroySurfaces( VADriverContextP ctx, + VASurfaceID *surface_list, + int num_surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaSyncSurface( VADriverContextP ctx, + VASurfaceID render_target) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaQuerySurfaceStatus( VADriverContextP ctx, + VASurfaceID render_target, + VASurfaceStatus *status) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaPutSurface( VADriverContextP ctx, + VASurfaceID surface, + void* draw, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, + unsigned int number_cliprects, + unsigned int flags) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaLockSurface( VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *luma_stride, + unsigned int *chroma_u_stride, + unsigned int *chroma_v_stride, + unsigned int *luma_offset, + unsigned int *chroma_u_offset, + unsigned int *chroma_v_offset, + unsigned int *buffer_name, + void **buffer) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus vlVaUnlockSurface( VADriverContextP ctx, + VASurfaceID surface) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/vdpau/Makefile b/src/gallium/state_trackers/vdpau/Makefile new file mode 100644 index 00000000000..0e68d4fe007 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/Makefile @@ -0,0 +1,29 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = vdpautracker + +VDPAU_MAJOR = 1 +VDPAU_MINOR = 0 +LIBRARY_DEFINES = -DVER_MAJOR=$(VDPAU_MAJOR) -DVER_MINOR=$(VDPAU_MINOR) $(STATE_TRACKER_DEFINES) + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I vdpau) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = htab.c \ + ftab.c \ + device.c \ + query.c \ + surface.c \ + decode.c \ + presentation.c \ + bitmap.c \ + mpeg2_bitstream_parser.c \ + output.c \ + preemption.c \ + mixer.c + + +include ../../Makefile.template + diff --git a/src/gallium/state_trackers/vdpau/bitmap.c b/src/gallium/state_trackers/vdpau/bitmap.c new file mode 100644 index 00000000000..f1a9d9a6828 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/bitmap.c @@ -0,0 +1,75 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vdpau/vdpau.h> +#include "vdpau_private.h" +#include <util/u_debug.h> + +VdpStatus +vlVdpBitmapSurfaceCreate( VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpBool frequently_accessed, + VdpBitmapSurface *surface) +{ + debug_printf("[VDPAU] Creating a bitmap surface\n"); + if (!surface) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceDestroy ( VdpBitmapSurface surface ) +{ + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceGetParameters ( VdpBitmapSurface surface, + VdpRGBAFormat *rgba_format, + uint32_t *width, uint32_t *height, + VdpBool *frequently_accessed) +{ + if (!(rgba_format && width && height && frequently_accessed)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfacePutBitsNative ( VdpBitmapSurface surface, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect ) +{ + if (!(source_data && source_pitches && destination_rect)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +}
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/color.c b/src/gallium/state_trackers/vdpau/color.c new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/gallium/state_trackers/vdpau/color.c diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c new file mode 100644 index 00000000000..5d3674c5eb2 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/decode.c @@ -0,0 +1,309 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include "mpeg2_bitstream_parser.h" +#include <util/u_memory.h> +#include <util/u_math.h> +#include <pipe/p_video_context.h> +#include <util/u_debug.h> + +VdpStatus +vlVdpDecoderCreate ( VdpDevice device, + VdpDecoderProfile profile, + uint32_t width, uint32_t height, + uint32_t max_references, + VdpDecoder *decoder +) +{ + enum pipe_video_profile p_profile = PIPE_VIDEO_PROFILE_UNKNOWN; + VdpStatus ret = VDP_STATUS_OK; + vlVdpDecoder *vldecoder = NULL; + + debug_printf("[VDPAU] Creating decoder\n"); + + if (!decoder) + return VDP_STATUS_INVALID_POINTER; + + if (!(width && height)) + return VDP_STATUS_INVALID_VALUE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) { + ret = VDP_STATUS_INVALID_HANDLE; + goto inv_device; + } + + vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); + if (!vldecoder) { + ret = VDP_STATUS_RESOURCES; + goto no_decoder; + } + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + ret = VDP_STATUS_INVALID_DECODER_PROFILE; + goto inv_profile; + } + + // TODO: Define max_references. Used mainly for H264 + + vldecoder->profile = p_profile; + vldecoder->height = height; + vldecoder->width = width; + vldecoder->device = dev; + vldecoder->vctx = NULL; + + *decoder = vlAddDataHTAB(vldecoder); + if (*decoder == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + debug_printf("[VDPAU] Decoder created succesfully\n"); + + return VDP_STATUS_OK; + + no_handle: + FREE(vldecoder); + inv_profile: + no_screen: + no_decoder: + inv_device: + return ret; +} + +VdpStatus +vlVdpDecoderDestroy (VdpDecoder decoder +) +{ + debug_printf("[VDPAU] Destroying decoder\n"); + vlVdpDecoder *vldecoder; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) { + return VDP_STATUS_INVALID_HANDLE; + } + + if (vldecoder->vctx) + { + if (vldecoder->vctx->vscreen) + vl_screen_destroy(vldecoder->vctx->vscreen); + } + + if (vldecoder->vctx) + vl_video_destroy(vldecoder->vctx); + + FREE(vldecoder); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpCreateSurfaceTarget (vlVdpDecoder *vldecoder, + vlVdpSurface *vlsurf +) +{ + struct pipe_resource tmplt; + struct pipe_resource *surf_tex; + struct pipe_video_context *vctx; + + debug_printf("[VDPAU] Creating surface\n"); + + if(!(vldecoder && vlsurf)) + return VDP_STATUS_INVALID_POINTER; + + vctx = vldecoder->vctx->vpipe; + + memset(&tmplt, 0, sizeof(struct pipe_resource)); + tmplt.target = PIPE_TEXTURE_2D; + tmplt.format = vctx->get_param(vctx,PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT); + tmplt.last_level = 0; + + if (vctx->is_format_supported(vctx, tmplt.format, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, + PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) { + tmplt.width0 = vlsurf->width; + tmplt.height0 = vlsurf->height; + } + else { + assert(vctx->is_format_supported(vctx, tmplt.format, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, + PIPE_TEXTURE_GEOM_NON_SQUARE)); + tmplt.width0 = util_next_power_of_two(vlsurf->width); + tmplt.height0 = util_next_power_of_two(vlsurf->height); + } + + tmplt.depth0 = 1; + tmplt.usage = PIPE_USAGE_DEFAULT; + tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + tmplt.flags = 0; + + surf_tex = vctx->screen->resource_create(vctx->screen, &tmplt); + + vlsurf->psurface = vctx->screen->get_tex_surface(vctx->screen, surf_tex, 0, 0, 0, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET); + + pipe_resource_reference(&surf_tex, NULL); + + if (!vlsurf->psurface) + return VDP_STATUS_RESOURCES; + debug_printf("[VDPAU] Done creating surface\n"); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderRenderMpeg2 (vlVdpDecoder *vldecoder, + vlVdpSurface *vlsurf, + VdpPictureInfoMPEG1Or2 *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers + ) +{ + struct pipe_video_context *vpipe; + vlVdpSurface *t_vdp_surf; + vlVdpSurface *p_vdp_surf; + vlVdpSurface *f_vdp_surf; + struct pipe_surface *t_surf; + struct pipe_surface *p_surf; + struct pipe_surface *f_surf; + uint32_t num_macroblocks; + struct pipe_mpeg12_macroblock *pipe_macroblocks; + VdpStatus ret; + + debug_printf("[VDPAU] Decoding MPEG2\n"); + + t_vdp_surf = vlsurf; + + /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ + if (picture_info->backward_reference == VDP_INVALID_HANDLE) + p_vdp_surf = NULL; + else { + p_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference); + if (!p_vdp_surf) + return VDP_STATUS_INVALID_HANDLE; + } + + if (picture_info->forward_reference == VDP_INVALID_HANDLE) + f_vdp_surf = NULL; + else { + f_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference); + if (!f_vdp_surf) + return VDP_STATUS_INVALID_HANDLE; + } + + + if (f_vdp_surf == VDP_INVALID_HANDLE) f_vdp_surf = NULL; + + ret = vlVdpCreateSurfaceTarget(vldecoder,t_vdp_surf); + + vpipe = vldecoder->vctx->vpipe; + + if (vlVdpMPEG2BitstreamToMacroblock(vpipe->screen, bitstream_buffers, bitstream_buffer_count, + &num_macroblocks, &pipe_macroblocks)) + { + debug_printf("[VDPAU] Error in frame-header. Skipping.\n"); + + ret = VDP_STATUS_OK; + goto skip_frame; + } + + vpipe->set_decode_target(vpipe,t_surf); + vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks, (struct pipe_macroblock *)pipe_macroblocks, NULL); + + skip_frame: + return ret; +} + +VdpStatus +vlVdpDecoderRender (VdpDecoder decoder, + VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers +) +{ + vlVdpDecoder *vldecoder; + vlVdpSurface *vlsurf; + struct vl_screen *vscreen; + VdpStatus ret; + debug_printf("[VDPAU] Decoding\n"); + + if (!(picture_info && bitstream_buffers)) + return VDP_STATUS_INVALID_POINTER; + + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); + if (!vlsurf) + return VDP_STATUS_INVALID_HANDLE; + + if (vlsurf->device != vldecoder->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + /* Test doesn't make sence */ + /*if (vlsurf->chroma_format != vldecoder->chroma_format) + return VDP_STATUS_INVALID_CHROMA_TYPE;*/ + + vscreen = vl_screen_create(vldecoder->device->display, vldecoder->device->screen); + if (!vscreen) + return VDP_STATUS_RESOURCES; + + vldecoder->vctx = vl_video_create(vscreen, vldecoder->profile, vlsurf->chroma_format, vldecoder->width, vldecoder->height); + if (!vldecoder->vctx) + return VDP_STATUS_RESOURCES; + + // TODO: Right now only mpeg2 is supported. + switch (vldecoder->vctx->vpipe->profile) { + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + ret = vlVdpDecoderRenderMpeg2(vldecoder,vlsurf,(VdpPictureInfoMPEG1Or2 *)picture_info, + bitstream_buffer_count,bitstream_buffers); + break; + default: + return VDP_STATUS_INVALID_DECODER_PROFILE; + } + assert(0); + + return ret; +} + +VdpStatus +vlVdpGenerateCSCMatrix( + VdpProcamp *procamp, + VdpColorStandard standard, + VdpCSCMatrix *csc_matrix) +{ + debug_printf("[VDPAU] Generating CSCMatrix\n"); + if (!(csc_matrix && procamp)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_OK; +}
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c new file mode 100644 index 00000000000..496e2b8def0 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/device.c @@ -0,0 +1,198 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton og Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <pipe/p_compiler.h> +#include <pipe/p_video_context.h> +#include <vl_winsys.h> +#include <util/u_memory.h> +#include <util/u_debug.h> +#include "vdpau_private.h" + + +PUBLIC VdpStatus +vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, VdpGetProcAddress **get_proc_address) +{ + VdpStatus ret; + vlVdpDevice *dev = NULL; + + if (!(display && device && get_proc_address)) + return VDP_STATUS_INVALID_POINTER; + + if (!vlCreateHTAB()) { + ret = VDP_STATUS_RESOURCES; + goto no_htab; + } + + dev = CALLOC(1, sizeof(vlVdpDevice)); + if (!dev) { + ret = VDP_STATUS_RESOURCES; + goto no_dev; + } + + dev->display = display; + dev->screen = screen; + dev->vscreen = vl_screen_create(display, screen); + if (!dev->vscreen) + { + ret = VDP_STATUS_RESOURCES; + goto no_vscreen; + } + + *device = vlAddDataHTAB(dev); + if (*device == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + *get_proc_address = &vlVdpGetProcAddress; + debug_printf("[VDPAU] Device created succesfully\n"); + + return VDP_STATUS_OK; + +no_handle: + /* Destroy vscreen */ +no_vscreen: + FREE(dev); +no_dev: + vlDestroyHTAB(); +no_htab: + return ret; +} + +PUBLIC VdpStatus +vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable,VdpPresentationQueueTarget *target) +{ + VdpStatus ret; + vlVdpPresentationQueueTarget *pqt = NULL; + + debug_printf("[VDPAU] Creating PresentationQueueTarget\n"); + + if (!drawable) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pqt = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pqt) + return VDP_STATUS_RESOURCES; + + pqt->device = dev; + pqt->drawable = drawable; + + *target = vlAddDataHTAB(pqt); + if (*target == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + + return VDP_STATUS_OK; + no_handle: + FREE(dev); + return ret; +} + +VdpStatus +vlVdpDeviceDestroy(VdpDevice device) +{ + debug_printf("[VDPAU] Destroying destroy\n"); + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + FREE(dev); + vlDestroyHTAB(); + + debug_printf("[VDPAU] Device destroyed succesfully\n"); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) +{ + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + if (!function_pointer) + return VDP_STATUS_INVALID_POINTER; + + if (!vlGetFuncFTAB(function_id, function_pointer)) + return VDP_STATUS_INVALID_FUNC_ID; + + return VDP_STATUS_OK; +} + +#define _ERROR_TYPE(TYPE,STRING) \ + case TYPE: \ + return STRING; \ + break + +char const * +vlVdpGetErrorString ( +VdpStatus status) +{ + switch (status) + { + _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); + _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); + _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); + _ERROR_TYPE(VDP_STATUS_INVALID_HANDLE,"An invalid handle value was provided. Either the handle does not exist at all, or refers to an object of an incorrect type."); + _ERROR_TYPE(VDP_STATUS_INVALID_POINTER ,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); + _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE ,"An invalid/unsupported VdpChromaType value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER ,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ + For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ + If presented with a VdpVideoSurface of a different size, this error will be raised."); + _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ + This is a catch-all error code for values of type other than those with a specific error code."); + _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ + This implies that the implementation is older than the header file the application was built against."); + _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); + _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ + that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ + all supplied surfaces must have been created within the context of the same VdpDevice object. \ + This error is raised if they were not."); + _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); + } +} diff --git a/src/gallium/state_trackers/vdpau/ftab.c b/src/gallium/state_trackers/vdpau/ftab.c new file mode 100644 index 00000000000..de08b810268 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/ftab.c @@ -0,0 +1,122 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include "vdpau_private.h" + +static void* ftab[67] = +{ + &vlVdpGetErrorString, /* VDP_FUNC_ID_GET_ERROR_STRING */ + &vlVdpGetProcAddress, /* VDP_FUNC_ID_GET_PROC_ADDRESS */ + &vlVdpGetApiVersion, /* VDP_FUNC_ID_GET_API_VERSION */ + 0x55, /* DUMMY */ + &vlVdpGetInformationString, /* VDP_FUNC_ID_GET_INFORMATION_STRING */ + &vlVdpDeviceDestroy, /* VDP_FUNC_ID_DEVICE_DESTROY */ + &vlVdpGenerateCSCMatrix, /* VDP_FUNC_ID_GENERATE_CSC_MATRIX */ + &vlVdpVideoSurfaceQueryCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES */ + &vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpVideoSurfaceCreate, /* VDP_FUNC_ID_VIDEO_SURFACE_CREATE */ + &vlVdpVideoSurfaceDestroy, /* VDP_FUNC_ID_VIDEO_SURFACE_DESTROY */ + &vlVdpVideoSurfaceGetParameters, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS */ + &vlVdpVideoSurfaceGetBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR */ + &vlVdpVideoSurfacePutBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpOutputSurfaceQueryCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES */ + &vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES */ + 0x2, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES */ + &vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpOutputSurfaceCreate, /* VDP_FUNC_ID_OUTPUT_SURFACE_CREATE */ + 0x3, /* VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY */ + 0x4, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS */ + 0x5, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE */ + 0x6, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE */ + 0x7, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED */ + 0x8, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpBitmapSurfaceQueryCapabilities, /* VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES */ + &vlVdpBitmapSurfaceCreate, /* VDP_FUNC_ID_BITMAP_SURFACE_CREATE */ + &vlVdpBitmapSurfaceDestroy, /* VDP_FUNC_ID_BITMAP_SURFACE_DESTROY */ + &vlVdpBitmapSurfaceGetParameters, /* VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS */ + &vlVdpBitmapSurfacePutBitsNative, /* VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE */ + 0x55, /* DUMMY */ + 0x55, /* DUMMY */ + 0x55, /* DUMMY */ + 0x9, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE */ + 0x10, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE */ + 0x11, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_VIDEO_SURFACE_LUMA */ + &vlVdpDecoderQueryCapabilities, /* VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES */ + &vlVdpDecoderCreate, /* VDP_FUNC_ID_DECODER_CREATE */ + &vlVdpDecoderDestroy, /* VDP_FUNC_ID_DECODER_DESTROY */ + 0x12, /* VDP_FUNC_ID_DECODER_GET_PARAMETERS */ + &vlVdpDecoderRender, /* VDP_FUNC_ID_DECODER_RENDER */ + &vlVdpVideoMixerQueryFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT */ + &vlVdpVideoMixerQueryParameterSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT */ + &vlVdpVideoMixerQueryAttributeSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT */ + &vlVdpVideoMixerQueryParameterValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE */ + &vlVdpVideoMixerQueryAttributeValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE */ + &vlVdpVideoMixerCreate, /* VDP_FUNC_ID_VIDEO_MIXER_CREATE */ + &vlVdpVideoMixerSetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES */ + &vlVdpVideoMixerSetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES */ + 0x16, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT */ + 0x17, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES */ + 0x18, /* VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES */ + 0x19, /* VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES */ + 0x20, /* VDP_FUNC_ID_VIDEO_MIXER_DESTROY */ + &vlVdpVideoMixerRender, /* VDP_FUNC_ID_VIDEO_MIXER_RENDER */ + &vlVdpPresentationQueueTargetDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY */ + &vlVdpPresentationQueueCreate, /* VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE */ + &vlVdpPresentationQueueDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY */ + &vlVdpPresentationQueueSetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR */ + &vlVdpPresentationQueueGetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR */ + 0x55, /* DUMMY */ + 0x55, /* DUMMY */ + &vlVdpPresentationQueueGetTime, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME */ + &vlVdpPresentationQueueDisplay, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY */ + &vlVdpPresentationQueueBlockUntilSurfaceIdle, /* VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE */ + &vlVdpPresentationQueueQuerySurfaceStatus, /* VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS */ + &vlVdpPreemptionCallbackRegister /* VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER */ +}; + +static void* ftab_winsys[1] = +{ + &vlVdpPresentationQueueTargetCreateX11 /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */ +}; + +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func) +{ + assert(func); + if (function_id < VDP_FUNC_ID_BASE_WINSYS) { + if (function_id > 66) + return FALSE; + *func = ftab[function_id]; + } + else { + function_id -= VDP_FUNC_ID_BASE_WINSYS; + if (function_id > 0) + return FALSE; + *func = ftab_winsys[function_id]; + } + return TRUE; +} diff --git a/src/gallium/state_trackers/vdpau/htab.c b/src/gallium/state_trackers/vdpau/htab.c new file mode 100644 index 00000000000..0c958055374 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/htab.c @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_handle_table.h> +#include <os/os_thread.h> +#include "vdpau_private.h" + +#ifdef VL_HANDLES +static struct handle_table *htab = NULL; +pipe_static_mutex(htab_lock); +#endif + +boolean vlCreateHTAB(void) +{ +#ifdef VL_HANDLES + boolean ret; + /* Make sure handle table handles match VDPAU handles. */ + assert(sizeof(unsigned) <= sizeof(vlHandle)); + pipe_mutex_lock(htab_lock); + if (!htab) + htab = handle_table_create(); + ret = htab != NULL; + pipe_mutex_unlock(htab_lock); + return ret; +#else + return TRUE; +#endif +} + +void vlDestroyHTAB(void) +{ +#ifdef VL_HANDLES + pipe_mutex_lock(htab_lock); + if (htab) { + handle_table_destroy(htab); + htab = NULL; + } + pipe_mutex_unlock(htab_lock); +#endif +} + +vlHandle vlAddDataHTAB(void *data) +{ + assert(data); +#ifdef VL_HANDLES + vlHandle handle = 0; + pipe_mutex_lock(htab_lock); + if (htab) + handle = handle_table_add(htab, data); + pipe_mutex_unlock(htab_lock); + return handle; +#else + return (vlHandle)data; +#endif +} + +void* vlGetDataHTAB(vlHandle handle) +{ + assert(handle); +#ifdef VL_HANDLES + void *data = NULL; + pipe_mutex_lock(htab_lock); + if (htab) + data = handle_table_get(htab, handle); + pipe_mutex_unlock(htab_lock); + return data; +#else + return (void*)handle; +#endif +} diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c new file mode 100644 index 00000000000..124125ebaad --- /dev/null +++ b/src/gallium/state_trackers/vdpau/mixer.c @@ -0,0 +1,140 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + #include <vdpau/vdpau.h> + #include <util/u_memory.h> + #include <util/u_debug.h> + #include "vdpau_private.h" + + + VdpStatus + vlVdpVideoMixerCreate (VdpDevice device, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + uint32_t parameter_count, + VdpVideoMixerParameter const *parameters, + void const *const *parameter_values, + VdpVideoMixer *mixer) +{ + VdpStatus ret; + vlVdpVideoMixer *vmixer = NULL; + + debug_printf("[VDPAU] Creating VideoMixer\n"); + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); + if (!vmixer) + return VDP_STATUS_RESOURCES; + + vmixer->device = dev; + /* + * TODO: Handle features and parameters + * */ + + *mixer = vlAddDataHTAB(vmixer); + if (*mixer == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + + return VDP_STATUS_OK; + no_handle: + return ret; +} + +VdpStatus +vlVdpVideoMixerSetFeatureEnables ( + VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool const *feature_enables) +{ + debug_printf("[VDPAU] Setting VideoMixer features\n"); + + if (!(features && feature_enables)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + /* + * TODO: Set features + * */ + + + return VDP_STATUS_OK; +} + +VdpStatus vlVdpVideoMixerRender ( + VdpVideoMixer mixer, + VdpOutputSurface background_surface, + VdpRect const *background_source_rect, + VdpVideoMixerPictureStructure current_picture_structure, + uint32_t video_surface_past_count, + VdpVideoSurface const *video_surface_past, + VdpVideoSurface video_surface_current, + uint32_t video_surface_future_count, + VdpVideoSurface const *video_surface_future, + VdpRect const *video_source_rect, + VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpRect const *destination_video_rect, + uint32_t layer_count, + VdpLayer const *layers) +{ + if (!(background_source_rect && video_surface_past && video_surface_future && video_source_rect && destination_rect && destination_video_rect && layers)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerSetAttributeValues ( + VdpVideoMixer mixer, + uint32_t attribute_count, + VdpVideoMixerAttribute const *attributes, + void const *const *attribute_values) +{ + if (!(attributes && attribute_values)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + /* + * TODO: Implement the function + * + * */ + + return VDP_STATUS_OK; +}
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c new file mode 100644 index 00000000000..90936584893 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c @@ -0,0 +1,149 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include "mpeg2_bitstream_parser.h" + +int +vlVdpMPEG2NextStartCode(struct vdpMPEG2BitstreamParser *parser) +{ + uint32_t integer = 0xffffff00; + uint8_t * ptr_read = parser->ptr_bitstream; + int8_t * bytes_to_end; + + bytes_to_end = parser->ptr_bitstream_end - parser->ptr_bitstream; + + /* Read byte after byte, until startcode is found */ + while(integer != 0x00000100) + { + if (bytes_to_end <= 0) + { + parser->state = MPEG2_BITSTREAM_DONE; + parser->code = 0; + return 0; + } + integer = ( integer | *ptr_read++ ) << 8; + bytes_to_end--; + } + parser->ptr_bitstream = ptr_read; + parser->code = parser->ptr_bitstream; + /* start_code found. rewind cursor a byte */ + //parser->cursor -= 8; + + return 0; +} + +int +vlVdpMPEG2BitstreamToMacroblock ( + struct pipe_screen *screen, + VdpBitstreamBuffer const *bitstream_buffers, + uint32_t bitstream_buffer_count, + unsigned int *num_macroblocks, + struct pipe_mpeg12_macroblock **pipe_macroblocks) +{ + bool b_header_done = false; + struct vdpMPEG2BitstreamParser parser; + + #if(1) + FILE *fp; + + if ((fp = fopen("binout", "w"))==NULL) { + printf("Cannot open file.\n"); + exit(1); + } + fwrite(bitstream_buffers[0].bitstream, 1, bitstream_buffers[0].bitstream_bytes, fp); + fclose(fp); + + #endif + + + debug_printf("[VDPAU] Starting decoding MPEG2 stream\n"); + + num_macroblocks[0] = 0; + + memset(&parser,0,sizeof(parser)); + parser.state = MPEG2_HEADER_START_CODE; + parser.ptr_bitstream = (unsigned char *)bitstream_buffers[0].bitstream; + parser.ptr_bitstream_end = parser.ptr_bitstream + bitstream_buffers[0].bitstream_bytes; + + /* Main header parser loop */ + while(!b_header_done) + { + switch (parser.state) + { + case MPEG2_SEEK_HEADER: + if (vlVdpMPEG2NextStartCode(&parser)) + exit(1); + break; + /* Start_code found */ + switch (parser.code) + { + /* sequence_header_code */ + case 0xB3: + debug_printf("[VDPAU][Bitstream parser] Sequence header code found\n"); + + /* We dont need to read this, because we already have this information */ + break; + case 0xB5: + debug_printf("[VDPAU][Bitstream parser] Extension start code found\n"); + //exit(1); + break; + + case 0xB8: + debug_printf("[VDPAU][Bitstream parser] Extension start code found\n"); + //exit(1); + break; + + } + + break; + case MPEG2_BITSTREAM_DONE: + if (parser.cur_bitstream < bitstream_buffer_count - 1) + { + debug_printf("[VDPAU][Bitstream parser] Done parsing current bitstream. Moving to the next\n"); + parser.cur_bitstream++; + parser.ptr_bitstream = (unsigned char *)bitstream_buffers[parser.cur_bitstream].bitstream; + parser.ptr_bitstream_end = parser.ptr_bitstream + bitstream_buffers[parser.cur_bitstream].bitstream_bytes; + parser.state = MPEG2_HEADER_START_CODE; + } + else + { + debug_printf("[VDPAU][Bitstream parser] Done with frame\n"); + exit(0); + // return 0; + } + break; + + } + + + } + + + return 0; +} + diff --git a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h new file mode 100644 index 00000000000..25f3516f821 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef MPEG2_BITSTREAM_PARSER_H +#define MPEG2_BITSTREAM_PARSER_H + +#include <vdpau/vdpau.h> +#include <pipe/p_video_state.h> +#include "vdpau_private.h" + +enum vdpMPEG2States +{ + MPEG2_SEEK_HEADER, + MPEG2_HEADER_DONE, + MPEG2_BITSTREAM_DONE, + MPEG2_HEADER_START_CODE +}; + + +struct vdpMPEG2BitstreamParser +{ + enum vdpMPEG2States state; + uint32_t cur_bitstream; + const uint8_t *ptr_bitstream_end; + const uint8_t *ptr_bitstream; + uint8_t code; + + /* The decoded bitstream goes here: */ + /* Sequence_header_info */ + uint32_t horizontal_size_value; +}; + +int +vlVdpMPEG2BitstreamToMacroblock(struct pipe_screen *screen, + VdpBitstreamBuffer const *bitstream_buffers, + uint32_t bitstream_buffer_count, + unsigned int *num_macroblocks, + struct pipe_mpeg12_macroblock **pipe_macroblocks); + + +#endif // MPEG2_BITSTREAM_PARSER_H diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c new file mode 100644 index 00000000000..20097eaf98c --- /dev/null +++ b/src/gallium/state_trackers/vdpau/output.c @@ -0,0 +1,64 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include <vdpau/vdpau.h> +#include <util/u_debug.h> +#include <util/u_memory.h> + +VdpStatus +vlVdpOutputSurfaceCreate ( VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpOutputSurface *surface) +{ + vlVdpOutputSurface *vlsurface = NULL; + + debug_printf("[VDPAU] Creating output surface\n"); + if (!(width && height)) + return VDP_STATUS_INVALID_SIZE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); + if (!vlsurface) + return VDP_STATUS_RESOURCES; + + vlsurface->width = width; + vlsurface->height = height; + vlsurface->format = FormatRGBAToPipe(rgba_format); + + *surface = vlAddDataHTAB(vlsurface); + if (*surface == 0) { + FREE(dev); + return VDP_STATUS_ERROR; + } + + return VDP_STATUS_OK; +}
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/preemption.c b/src/gallium/state_trackers/vdpau/preemption.c new file mode 100644 index 00000000000..4572bdcfe6d --- /dev/null +++ b/src/gallium/state_trackers/vdpau/preemption.c @@ -0,0 +1,39 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + #include <vdpau/vdpau.h> + + void vlVdpPreemptionCallback (VdpDevice device, void *context) + { + /* TODO: Implement preemption */ + } + + VdpStatus vlVdpPreemptionCallbackRegister (VdpDevice device, VdpPreemptionCallback callback, void *context) + { + + return VDP_STATUS_OK; + }
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c new file mode 100644 index 00000000000..5f545d0bb27 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/presentation.c @@ -0,0 +1,149 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include <vdpau/vdpau.h> +#include <util/u_debug.h> +#include <util/u_memory.h> + +VdpStatus +vlVdpPresentationQueueTargetDestroy (VdpPresentationQueueTarget presentation_queue_target) +{ + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueCreate ( VdpDevice device, + VdpPresentationQueueTarget presentation_queue_target, + VdpPresentationQueue *presentation_queue) +{ + debug_printf("[VDPAU] Creating PresentationQueue\n"); + VdpStatus ret; + vlVdpPresentationQueue *pq = NULL; + + if (!presentation_queue) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target); + if (!pqt) + return VDP_STATUS_INVALID_HANDLE; + + if (dev != pqt->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + pq = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pq) + return VDP_STATUS_RESOURCES; + + *presentation_queue = vlAddDataHTAB(pq); + if (*presentation_queue == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + + return VDP_STATUS_OK; + no_handle: + FREE(pq); + return ret; +} + +VdpStatus +vlVdpPresentationQueueDestroy (VdpPresentationQueue presentation_queue) +{ + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueSetBackgroundColor ( VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueGetBackgroundColor ( VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueGetTime ( VdpPresentationQueue presentation_queue, + VdpTime *current_time) +{ + if (!current_time) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueDisplay ( VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + uint32_t clip_width, + uint32_t clip_height, + VdpTime earliest_presentation_time) +{ + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueBlockUntilSurfaceIdle ( VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpTime *first_presentation_time) +{ + if (!first_presentation_time) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueQuerySurfaceStatus ( VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpPresentationQueueStatus *status, + VdpTime *first_presentation_time) +{ + if (!(status && first_presentation_time)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +}
\ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c new file mode 100644 index 00000000000..a3a8500a6f7 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/query.c @@ -0,0 +1,282 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include <vl_winsys.h> +#include <assert.h> +#include <pipe/p_screen.h> +#include <pipe/p_defines.h> +#include <math.h> +#include <util/u_debug.h> + + +VdpStatus +vlVdpGetApiVersion(uint32_t *api_version) +{ + if (!api_version) + return VDP_STATUS_INVALID_POINTER; + + *api_version = 1; + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpGetInformationString(char const **information_string) +{ + if (!information_string) + return VDP_STATUS_INVALID_POINTER; + + *information_string = INFORMATION_STRING; + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + struct vl_screen *vlscreen; + uint32_t max_2d_texture_level; + VdpStatus ret; + + debug_printf("[VDPAU] Querying video surfaces\n"); + + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) + return VDP_STATUS_RESOURCES; + + /* XXX: Current limits */ + *is_supported = true; + if (surface_chroma_type != VDP_CHROMA_TYPE_420) { + *is_supported = false; + goto no_sup; + } + + max_2d_texture_level = vlscreen->pscreen->get_param( vlscreen->pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS ); + if (!max_2d_texture_level) { + ret = VDP_STATUS_RESOURCES; + goto no_sup; + } + + /* I am not quite sure if it is max_2d_texture_level-1 or just max_2d_texture_level */ + *max_width = *max_height = pow(2,max_2d_texture_level-1); + + vl_screen_destroy(vlscreen); + + return VDP_STATUS_OK; + no_sup: + return ret; +} + +VdpStatus +vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + struct vl_screen *vlscreen; + + debug_printf("[VDPAU] Querying get put video surfaces\n"); + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) + return VDP_STATUS_RESOURCES; + + if (bits_ycbcr_format != VDP_YCBCR_FORMAT_Y8U8V8A8 && bits_ycbcr_format != VDP_YCBCR_FORMAT_V8U8Y8A8) + *is_supported = vlscreen->pscreen->is_format_supported(vlscreen->pscreen, + FormatToPipe(bits_ycbcr_format), + PIPE_TEXTURE_2D, + 1, + PIPE_BIND_RENDER_TARGET, + PIPE_TEXTURE_GEOM_NON_SQUARE ); + + vl_screen_destroy(vlscreen); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, + VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, + uint32_t *max_width, uint32_t *max_height) +{ + enum pipe_video_profile p_profile; + uint32_t max_decode_width; + uint32_t max_decode_height; + uint32_t max_2d_texture_level; + struct vl_screen *vlscreen; + + debug_printf("[VDPAU] Querying decoder\n"); + + if (!(is_supported && max_level && max_macroblocks && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) + return VDP_STATUS_RESOURCES; + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + if (p_profile != PIPE_VIDEO_PROFILE_MPEG2_SIMPLE && p_profile != PIPE_VIDEO_PROFILE_MPEG2_MAIN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + /* XXX hack, need to implement something more sane when the decoders have been implemented */ + max_2d_texture_level = vlscreen->pscreen->get_param( vlscreen->pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS ); + max_decode_width = max_decode_height = pow(2,max_2d_texture_level-2); + if (!(max_decode_width && max_decode_height)) + return VDP_STATUS_RESOURCES; + + *is_supported = true; + *max_width = max_decode_width; + *max_height = max_decode_height; + *max_level = 16; + *max_macroblocks = (max_decode_width/16) * (max_decode_height/16); + + vl_screen_destroy(vlscreen); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + debug_printf("[VDPAU] Querying ouput surfaces\n"); + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported) +{ + debug_printf("[VDPAU] Querying output surfaces get put native cap\n"); + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + debug_printf("[VDPAU] Querying output surfaces put ycrcb cap\n"); + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + debug_printf("[VDPAU] Querying bitmap surfaces\n"); + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature, + VdpBool *is_supported) +{ + debug_printf("[VDPAU] Querying mixer feature support\n"); + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter, + void *min_value, void *max_value) +{ + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute, + void *min_value, void *max_value) +{ + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c new file mode 100644 index 00000000000..9b6dac9c3f4 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/surface.c @@ -0,0 +1,193 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include <pipe/p_screen.h> +#include <pipe/p_state.h> +#include <util/u_memory.h> +#include <util/u_format.h> + +VdpStatus +vlVdpVideoSurfaceCreate(VdpDevice device, + VdpChromaType chroma_type, + uint32_t width, + uint32_t height, + VdpVideoSurface *surface) +{ + printf("[VDPAU] Creating a surface\n"); + + vlVdpSurface *p_surf; + VdpStatus ret; + + if (!(width && height)) + { + ret = VDP_STATUS_INVALID_SIZE; + goto inv_size; + } + + + if (!vlCreateHTAB()) { + ret = VDP_STATUS_RESOURCES; + goto no_htab; + } + + p_surf = CALLOC(1, sizeof(p_surf)); + if (!p_surf) { + ret = VDP_STATUS_RESOURCES; + goto no_res; + } + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) { + ret = VDP_STATUS_INVALID_HANDLE; + goto inv_device; + } + + p_surf->chroma_format = TypeToPipe(chroma_type); + p_surf->device = dev; + p_surf->width = width; + p_surf->height = height; + + *surface = vlAddDataHTAB(p_surf); + if (*surface == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: + FREE(p_surf->psurface); +inv_device: +no_surf: + FREE(p_surf); +no_res: + // vlDestroyHTAB(); XXX: Do not destroy this tab, I think. +no_htab: +inv_size: + return ret; +} + +VdpStatus +vlVdpVideoSurfaceDestroy ( VdpVideoSurface surface ) +{ + vlVdpSurface *p_surf; + + p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (p_surf->psurface) { + if (p_surf->psurface->texture) { + if (p_surf->psurface->texture->screen) + p_surf->psurface->texture->screen->tex_surface_destroy(p_surf->psurface); + } + } + FREE(p_surf); + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceGetParameters ( VdpVideoSurface surface, + VdpChromaType *chroma_type, + uint32_t *width, + uint32_t *height +) +{ + if (!(width && height && chroma_type)) + return VDP_STATUS_INVALID_POINTER; + + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + + if (!(p_surf->chroma_format > 0 && p_surf->chroma_format < 3)) + return VDP_STATUS_INVALID_CHROMA_TYPE; + + *width = p_surf->width; + *height = p_surf->height; + *chroma_type = PipeToType(p_surf->chroma_format); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceGetBitsYCbCr ( VdpVideoSurface surface, + VdpYCbCrFormat destination_ycbcr_format, + void *const *destination_data, + uint32_t const *destination_pitches +) +{ + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (!p_surf->psurface) + return VDP_STATUS_RESOURCES; + + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfacePutBitsYCbCr ( VdpVideoSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches +) +{ + uint32_t size_surface_bytes; + const struct util_format_description *format_desc; + enum pipe_format pformat = FormatToPipe(source_ycbcr_format); + + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + + //size_surface_bytes = ( source_pitches[0] * p_surf->height util_format_get_blockheight(pformat) ); + /*util_format_translate(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_x, unsigned dst_y, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height);*/ + + return VDP_STATUS_NO_IMPLEMENTATION; + +} diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h new file mode 100644 index 00000000000..1deea3a67d3 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h @@ -0,0 +1,278 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VDPAU_PRIVATE_H +#define VDPAU_PRIVATE_H + + +#include <vdpau/vdpau.h> +#include <vdpau/vdpau_x11.h> +#include <pipe/p_compiler.h> +#include <pipe/p_video_context.h> +#include <vl_winsys.h> +#include <assert.h> + +#define INFORMATION G3DVL VDPAU Driver Shared Library version VER_MAJOR.VER_MINOR +#define QUOTEME(x) #x +#define TOSTRING(x) QUOTEME(x) +#define INFORMATION_STRING TOSTRING(INFORMATION) +#define VL_HANDLES + +static enum pipe_video_chroma_format TypeToPipe(VdpChromaType vdpau_type) +{ + switch (vdpau_type) { + case VDP_CHROMA_TYPE_420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VDP_CHROMA_TYPE_422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VDP_CHROMA_TYPE_444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return -1; +} + +static VdpChromaType PipeToType(enum pipe_video_chroma_format pipe_type) +{ + switch (pipe_type) { + case PIPE_VIDEO_CHROMA_FORMAT_420: + return VDP_CHROMA_TYPE_420; + case PIPE_VIDEO_CHROMA_FORMAT_422: + return VDP_CHROMA_TYPE_422; + case PIPE_VIDEO_CHROMA_FORMAT_444: + return VDP_CHROMA_TYPE_444; + default: + assert(0); + } + + return -1; +} + + +static enum pipe_format FormatToPipe(VdpYCbCrFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_YCBCR_FORMAT_NV12: + return PIPE_FORMAT_NV12; + case VDP_YCBCR_FORMAT_YV12: + return PIPE_FORMAT_YV12; + case VDP_YCBCR_FORMAT_UYVY: + return PIPE_FORMAT_UYVY; + case VDP_YCBCR_FORMAT_YUYV: + return PIPE_FORMAT_YUYV; + case VDP_YCBCR_FORMAT_Y8U8V8A8: /* Not defined in p_format.h */ + return 0; + case VDP_YCBCR_FORMAT_V8U8Y8A8: + return PIPE_FORMAT_VUYA; + default: + assert(0); + } + + return -1; +} + +static enum pipe_format FormatRGBAToPipe(VdpRGBAFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_RGBA_FORMAT_A8: + return PIPE_FORMAT_A8_UNORM; + case VDP_RGBA_FORMAT_B10G10R10A2: + return PIPE_FORMAT_B10G10R10A2_UNORM; + case VDP_RGBA_FORMAT_B8G8R8A8: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case VDP_RGBA_FORMAT_R10G10B10A2: + return PIPE_FORMAT_R10G10B10A2_UNORM; + case VDP_RGBA_FORMAT_R8G8B8A8: + return PIPE_FORMAT_R8G8B8A8_UNORM; + default: + assert(0); + } + + return -1; +} + +static VdpYCbCrFormat PipeToFormat(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_NV12: + return VDP_YCBCR_FORMAT_NV12; + case PIPE_FORMAT_YV12: + return VDP_YCBCR_FORMAT_YV12; + case PIPE_FORMAT_UYVY: + return VDP_YCBCR_FORMAT_UYVY; + case PIPE_FORMAT_YUYV: + return VDP_YCBCR_FORMAT_YUYV; + //case PIPE_FORMAT_YUVA: + // return VDP_YCBCR_FORMAT_Y8U8V8A8; + case PIPE_FORMAT_VUYA: + return VDP_YCBCR_FORMAT_V8U8Y8A8; + default: + assert(0); + } + + return -1; +} + +static enum pipe_video_profile ProfileToPipe(VdpDecoderProfile vdpau_profile) +{ + switch (vdpau_profile) { + case VDP_DECODER_PROFILE_MPEG1: + return PIPE_VIDEO_PROFILE_MPEG1; + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: + return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; + case VDP_DECODER_PROFILE_MPEG2_MAIN: + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + case VDP_DECODER_PROFILE_H264_BASELINE: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case VDP_DECODER_PROFILE_H264_MAIN: /* Not defined in p_format.h */ + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case VDP_DECODER_PROFILE_H264_HIGH: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + default: + PIPE_VIDEO_PROFILE_UNKNOWN; + } + + return -1; +} + +typedef struct +{ + Display *display; + int screen; + struct vl_screen *vscreen; +} vlVdpDevice; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; +} vlVdpPresentationQueueTarget; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; +} vlVdpPresentationQueue; + +typedef struct +{ + vlVdpDevice *device; +} vlVdpVideoMixer; + +typedef struct +{ + vlVdpDevice *device; + uint32_t width; + uint32_t height; + uint32_t pitch; + struct pipe_surface *psurface; + enum pipe_video_chroma_format chroma_format; + uint8_t *data; +} vlVdpSurface; + +typedef struct +{ + vlVdpDevice *device; + uint32_t width; + uint32_t height; + enum pipe_format format; +} vlVdpOutputSurface; + +typedef struct +{ + vlVdpDevice *device; + struct vl_context *vctx; + enum pipe_video_chroma_format chroma_format; + enum pipe_video_profile profile; + uint32_t width; + uint32_t height; +} vlVdpDecoder; + +typedef uint32_t vlHandle; + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func); + +/* Public functions */ +VdpDeviceCreateX11 vdp_imp_device_create_x11; +VdpPresentationQueueTargetCreateX11 vlVdpPresentationQueueTargetCreateX11; + +/* Internal function pointers */ +VdpGetErrorString vlVdpGetErrorString; +VdpDeviceDestroy vlVdpDeviceDestroy; +VdpGetProcAddress vlVdpGetProcAddress; +VdpGetApiVersion vlVdpGetApiVersion; +VdpGetInformationString vlVdpGetInformationString; +VdpVideoSurfaceQueryCapabilities vlVdpVideoSurfaceQueryCapabilities; +VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities; +VdpDecoderQueryCapabilities vlVdpDecoderQueryCapabilities; +VdpOutputSurfaceQueryCapabilities vlVdpOutputSurfaceQueryCapabilities; +VdpOutputSurfaceQueryGetPutBitsNativeCapabilities vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities; +VdpOutputSurfaceQueryPutBitsYCbCrCapabilities vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities; +VdpBitmapSurfaceQueryCapabilities vlVdpBitmapSurfaceQueryCapabilities; +VdpVideoMixerQueryFeatureSupport vlVdpVideoMixerQueryFeatureSupport; +VdpVideoMixerQueryParameterSupport vlVdpVideoMixerQueryParameterSupport; +VdpVideoMixerQueryParameterValueRange vlVdpVideoMixerQueryParameterValueRange; +VdpVideoMixerQueryAttributeSupport vlVdpVideoMixerQueryAttributeSupport; +VdpVideoMixerQueryAttributeValueRange vlVdpVideoMixerQueryAttributeValueRange; +VdpVideoSurfaceCreate vlVdpVideoSurfaceCreate; +VdpVideoSurfaceDestroy vlVdpVideoSurfaceDestroy; +VdpVideoSurfaceGetParameters vlVdpVideoSurfaceGetParameters; +VdpVideoSurfaceGetBitsYCbCr vlVdpVideoSurfaceGetBitsYCbCr; +VdpVideoSurfacePutBitsYCbCr vlVdpVideoSurfacePutBitsYCbCr; +VdpDecoderCreate vlVdpDecoderCreate; +VdpDecoderDestroy vlVdpDecoderDestroy; +VdpDecoderRender vlVdpDecoderRender; +VdpOutputSurfaceCreate vlVdpOutputSurfaceCreate; +VdpBitmapSurfaceCreate vlVdpBitmapSurfaceCreate; +VdpBitmapSurfaceDestroy vlVdpBitmapSurfaceDestroy; +VdpBitmapSurfaceGetParameters vlVdpBitmapSurfaceGetParameters; +VdpBitmapSurfacePutBitsNative vlVdpBitmapSurfacePutBitsNative; +VdpPresentationQueueTargetDestroy vlVdpPresentationQueueTargetDestroy; +VdpPresentationQueueCreate vlVdpPresentationQueueCreate; +VdpPresentationQueueDestroy vlVdpPresentationQueueDestroy; +VdpPresentationQueueSetBackgroundColor vlVdpPresentationQueueSetBackgroundColor; +VdpPresentationQueueGetBackgroundColor vlVdpPresentationQueueGetBackgroundColor; +VdpPresentationQueueGetTime vlVdpPresentationQueueGetTime; +VdpPresentationQueueDisplay vlVdpPresentationQueueDisplay; +VdpPresentationQueueBlockUntilSurfaceIdle vlVdpPresentationQueueBlockUntilSurfaceIdle; +VdpPresentationQueueQuerySurfaceStatus vlVdpPresentationQueueQuerySurfaceStatus; +VdpPreemptionCallback vlVdpPreemptionCallback; +VdpPreemptionCallbackRegister vlVdpPreemptionCallbackRegister; +VdpVideoMixerSetFeatureEnables vlVdpVideoMixerSetFeatureEnables; +VdpVideoMixerCreate vlVdpVideoMixerCreate; +VdpVideoMixerRender vlVdpVideoMixerRender; +VdpVideoMixerSetAttributeValues vlVdpVideoMixerSetAttributeValues; +VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix; + + +#endif // VDPAU_PRIVATE_H diff --git a/src/gallium/state_trackers/xorg/xvmc/Makefile b/src/gallium/state_trackers/xorg/xvmc/Makefile new file mode 100644 index 00000000000..126dc6d58f1 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/Makefile @@ -0,0 +1,16 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = xvmctracker + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I xvmc) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = block.c \ + surface.c \ + context.c \ + subpicture.c \ + attributes.c + +include ../../../Makefile.template diff --git a/src/gallium/state_trackers/xorg/xvmc/attributes.c b/src/gallium/state_trackers/xorg/xvmc/attributes.c new file mode 100644 index 00000000000..d23d8635b66 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/attributes.c @@ -0,0 +1,50 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMClib.h> +#include <pipe/p_compiler.h> + +PUBLIC +XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number) +{ + return NULL; +} + +PUBLIC +Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value) +{ + return BadImplementation; +} + +PUBLIC +Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value) +{ + return BadImplementation; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/block.c b/src/gallium/state_trackers/xorg/xvmc/block.c new file mode 100644 index 00000000000..c7da7a84a7b --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/block.c @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> +#include <util/u_memory.h> +#include "xvmc_private.h" + +PUBLIC +Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->blocks); + + return Success; +} + +PUBLIC +Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->macro_blocks); + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/context.c b/src/gallium/state_trackers/xorg/xvmc/context.c new file mode 100644 index 00000000000..06a1633288b --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/context.c @@ -0,0 +1,298 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <X11/Xlibint.h> +#include <X11/extensions/XvMClib.h> +#include <pipe/p_screen.h> +#include <pipe/p_video_context.h> +#include <pipe/p_video_state.h> +#include <pipe/p_state.h> +#include <vl_winsys.h> +#include <util/u_memory.h> +#include <vl/vl_csc.h> +#include "xvmc_private.h" + +static Status Validate(Display *dpy, XvPortID port, int surface_type_id, + unsigned int width, unsigned int height, int flags, + bool *found_port, int *screen, int *chroma_format, + int *mc_type, int *surface_flags, + unsigned short *subpic_max_w, + unsigned short *subpic_max_h) +{ + bool found_surface = false; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + unsigned int max_width, max_height; + Status ret; + + assert(dpy); + assert(found_port); + assert(screen); + assert(chroma_format); + assert(mc_type); + assert(surface_flags); + assert(subpic_max_w); + assert(subpic_max_h); + + *found_port = false; + + for (unsigned int i = 0; i < XScreenCount(dpy); ++i) { + ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info); + if (ret != Success) + return ret; + + for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) { + for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) { + XvMCSurfaceInfo *surface_info; + + if (adaptor_info[j].base_id + k != port) + continue; + + *found_port = true; + + surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types); + if (!surface_info) { + XvFreeAdaptorInfo(adaptor_info); + return BadAlloc; + } + + for (unsigned int l = 0; l < num_types && !found_surface; ++l) { + if (surface_info[l].surface_type_id != surface_type_id) + continue; + + found_surface = true; + max_width = surface_info[l].max_width; + max_height = surface_info[l].max_height; + *chroma_format = surface_info[l].chroma_format; + *mc_type = surface_info[l].mc_type; + *surface_flags = surface_info[l].flags; + *subpic_max_w = surface_info[l].subpicture_max_width; + *subpic_max_h = surface_info[l].subpicture_max_height; + *screen = i; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \ + "[XvMC] screen=%u, port=%u\n" \ + "[XvMC] id=0x%08X\n" \ + "[XvMC] max width=%u, max height=%u\n" \ + "[XvMC] chroma format=0x%08X\n" \ + "[XvMC] acceleration level=0x%08X\n" \ + "[XvMC] flags=0x%08X\n" \ + "[XvMC] subpicture max width=%u, max height=%u\n", + i, port, surface_type_id, max_width, max_height, *chroma_format, + *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h); + } + + XFree(surface_info); + } + } + + XvFreeAdaptorInfo(adaptor_info); + } + + if (!*found_port) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n"); + return XvBadPort; + } + if (!found_surface) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n"); + return BadMatch; + } + if (width > max_width || height > max_height) { + XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n", + width, height, max_width, max_height); + return BadValue; + } + if (flags != XVMC_DIRECT && flags != 0) { + XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags); + return BadValue; + } + + return Success; +} + +static enum pipe_video_profile ProfileToPipe(int xvmc_profile) +{ + if (xvmc_profile & XVMC_MPEG_1) + assert(0); + if (xvmc_profile & XVMC_MPEG_2) + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + if (xvmc_profile & XVMC_H263) + assert(0); + if (xvmc_profile & XVMC_MPEG_4) + assert(0); + + assert(0); + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile); + + return -1; +} + +static enum pipe_video_chroma_format FormatToPipe(int xvmc_format) +{ + switch (xvmc_format) { + case XVMC_CHROMA_FORMAT_420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case XVMC_CHROMA_FORMAT_422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case XVMC_CHROMA_FORMAT_444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format); + + return -1; +} + +PUBLIC +Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, + int width, int height, int flags, XvMCContext *context) +{ + bool found_port; + int scrn; + int chroma_format; + int mc_type; + int surface_flags; + unsigned short subpic_max_w; + unsigned short subpic_max_h; + Status ret; + struct vl_screen *vscreen; + struct vl_context *vctx; + XvMCContextPrivate *context_priv; + float csc[16]; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + ret = Validate(dpy, port, surface_type_id, width, height, flags, + &found_port, &scrn, &chroma_format, &mc_type, &surface_flags, + &subpic_max_w, &subpic_max_h); + + /* Success and XvBadPort have the same value */ + if (ret != Success || !found_port) + return ret; + + /* XXX: Current limits */ + if (chroma_format != XVMC_CHROMA_FORMAT_420) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n"); + return BadImplementation; + } + if (mc_type != (XVMC_IDCT | XVMC_MOCOMP | XVMC_MPEG_2)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n"); + return BadImplementation; + } + if (surface_flags & XVMC_INTRA_UNSIGNED) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n"); + return BadImplementation; + } + + context_priv = CALLOC(1, sizeof(XvMCContextPrivate)); + if (!context_priv) + return BadAlloc; + + /* TODO: Reuse screen if process creates another context */ + vscreen = vl_screen_create(dpy, scrn); + + if (!vscreen) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n"); + FREE(context_priv); + return BadAlloc; + } + + vctx = vl_video_create(vscreen, ProfileToPipe(mc_type), + FormatToPipe(chroma_format), width, height); + + if (!vctx) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n"); + vl_screen_destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */ + vl_csc_get_matrix + ( + debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? + VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601, + NULL, true, csc + ); + vctx->vpipe->set_csc_matrix(vctx->vpipe, csc); + + context_priv->vctx = vctx; + context_priv->subpicture_max_width = subpic_max_w; + context_priv->subpicture_max_height = subpic_max_h; + + context->context_id = XAllocID(dpy); + context->surface_type_id = surface_type_id; + context->width = width; + context->height = height; + context->flags = flags; + context->port = port; + context->privData = context_priv; + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context); + + return Success; +} + +PUBLIC +Status XvMCDestroyContext(Display *dpy, XvMCContext *context) +{ + struct vl_screen *vscreen; + struct vl_context *vctx; + XvMCContextPrivate *context_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context); + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + vctx = context_priv->vctx; + pipe_surface_reference(&context_priv->backbuffer, NULL); + vscreen = vctx->vscreen; + vl_video_destroy(vctx); + vl_screen_destroy(vscreen); + FREE(context_priv); + context->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context); + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c new file mode 100644 index 00000000000..4a835c04d8a --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c @@ -0,0 +1,452 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <X11/Xlibint.h> +#include <X11/extensions/XvMClib.h> +#include <xorg/fourcc.h> +#include <vl_winsys.h> +#include <pipe/p_screen.h> +#include <pipe/p_video_context.h> +#include <pipe/p_state.h> +#include <util/u_memory.h> +#include <util/u_math.h> +#include "xvmc_private.h" + +#define FOURCC_RGB 0x0000003 + +static enum pipe_format XvIDToPipe(int xvimage_id) +{ + switch (xvimage_id) { + case FOURCC_RGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + return PIPE_FORMAT_NONE; + } +} + +static int PipeToComponentOrder(enum pipe_format format, char *component_order) +{ + assert(component_order); + + switch (format) { + case PIPE_FORMAT_B8G8R8X8_UNORM: + return 0; + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format); + component_order[0] = 0; + component_order[1] = 0; + component_order[2] = 0; + component_order[3] = 0; + } + + return 0; +} + +static Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id) +{ + XvImageFormatValues *subpictures; + int num_subpics; + unsigned int i; + + subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics); + if (num_subpics < 1) { + if (subpictures) + XFree(subpictures); + return BadMatch; + } + if (!subpictures) + return BadAlloc; + + for (i = 0; i < num_subpics; ++i) { + if (subpictures[i].id == xvimage_id) { + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \ + "[XvMC] port=%u\n" \ + "[XvMC] surface id=0x%08X\n" \ + "[XvMC] image id=0x%08X\n" \ + "[XvMC] type=%08X\n" \ + "[XvMC] byte order=%08X\n" \ + "[XvMC] bits per pixel=%u\n" \ + "[XvMC] format=%08X\n" \ + "[XvMC] num planes=%d\n", + port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order, + subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes); + if (subpictures[i].type == XvRGB) { + XVMC_MSG(XVMC_TRACE, "[XvMC] depth=%d\n" \ + "[XvMC] red mask=0x%08X\n" \ + "[XvMC] green mask=0x%08X\n" \ + "[XvMC] blue mask=0x%08X\n", + subpictures[i].depth, subpictures[i].red_mask, subpictures[i].green_mask, subpictures[i].blue_mask); + } + else if (subpictures[i].type == XvYUV) { + XVMC_MSG(XVMC_TRACE, "[XvMC] y sample bits=0x%08X\n" \ + "[XvMC] u sample bits=0x%08X\n" \ + "[XvMC] v sample bits=0x%08X\n" \ + "[XvMC] horz y period=%u\n" \ + "[XvMC] horz u period=%u\n" \ + "[XvMC] horz v period=%u\n" \ + "[XvMC] vert y period=%u\n" \ + "[XvMC] vert u period=%u\n" \ + "[XvMC] vert v period=%u\n", + subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits, + subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period, + subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period); + } + break; + } + } + + XFree(subpictures); + + return i < num_subpics ? Success : BadMatch; +} + +PUBLIC +Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture, + unsigned short width, unsigned short height, int xvimage_id) +{ + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + struct pipe_video_context *vpipe; + struct pipe_resource template; + struct pipe_resource *tex; + struct pipe_surface surf_template; + Status ret; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + context_priv = context->privData; + vpipe = context_priv->vctx->vpipe; + + if (!subpicture) + return XvMCBadSubpicture; + + if (width > context_priv->subpicture_max_width || + height > context_priv->subpicture_max_height) + return BadValue; + + ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id); + if (ret != Success) + return ret; + + subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate)); + if (!subpicture_priv) + return BadAlloc; + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + template.format = XvIDToPipe(xvimage_id); + template.last_level = 0; + if (vpipe->get_param(vpipe, PIPE_CAP_NPOT_TEXTURES)) { + template.width0 = width; + template.height0 = height; + } + else { + template.width0 = util_next_power_of_two(width); + template.height0 = util_next_power_of_two(height); + } + template.depth0 = 1; + template.usage = PIPE_USAGE_DYNAMIC; + template.bind = PIPE_BIND_SAMPLER_VIEW; + template.flags = 0; + + subpicture_priv->context = context; + tex = vpipe->screen->resource_create(vpipe->screen, &template); + + memset(&surf_template, 0, sizeof(surf_template)); + surf_template.format = tex->format; + surf_template.usage = PIPE_BIND_SAMPLER_VIEW; + subpicture_priv->sfc = vpipe->create_surface(vpipe, tex, &surf_template); + pipe_resource_reference(&tex, NULL); + if (!subpicture_priv->sfc) { + FREE(subpicture_priv); + return BadAlloc; + } + + subpicture->subpicture_id = XAllocID(dpy); + subpicture->context_id = context->context_id; + subpicture->xvimage_id = xvimage_id; + subpicture->width = width; + subpicture->height = height; + subpicture->num_palette_entries = 0; + subpicture->entry_bytes = PipeToComponentOrder(template.format, subpicture->component_order); + subpicture->privData = subpicture_priv; + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y, + unsigned short width, unsigned short height, unsigned int color) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + unsigned int tmp_color; + float color_f[4]; + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + /* Convert color to float */ + util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM, + color_f, 1, + &color, 4, + 0, 0, 1, 1); + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + /* TODO: Assert clear rect is within bounds? Or clip? */ + context_priv->vctx->vpipe->clear_render_target(context_priv->vctx->vpipe, + subpicture_priv->sfc, x, y, + color_f, + width, height); + + return Success; +} + +PUBLIC +Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image, + short srcx, short srcy, unsigned short width, unsigned short height, + short dstx, short dsty) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_video_context *vpipe; + struct pipe_transfer *xfer; + unsigned char *src, *dst, *dst_line; + unsigned x, y; + struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1}; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(image); + + if (subpicture->xvimage_id != image->id) + return BadMatch; + + /* No planar support for now */ + if (image->num_planes != 1) + return BadMatch; + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + vpipe = context_priv->vctx->vpipe; + + /* TODO: Assert rects are within bounds? Or clip? */ + + xfer = vpipe->get_transfer(vpipe, subpicture_priv->sfc->texture, + 0, PIPE_TRANSFER_WRITE, &dst_box); + if (!xfer) + return BadAlloc; + + src = image->data; + dst = vpipe->transfer_map(vpipe, xfer); + if (!dst) { + vpipe->transfer_destroy(vpipe, xfer); + return BadAlloc; + } + + switch (image->id) { + case FOURCC_RGB: + assert(subpicture_priv->sfc->format == XvIDToPipe(image->id)); + for (y = 0; y < height; ++y) { + dst_line = dst; + for (x = 0; x < width; ++x, src += 3, dst_line += 4) { + dst_line[0] = src[2]; /* B */ + dst_line[1] = src[1]; /* G */ + dst_line[2] = src[0]; /* R */ + } + dst += xfer->stride; + } + break; + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", image->id); + } + + vpipe->transfer_unmap(vpipe, xfer); + vpipe->transfer_destroy(vpipe, xfer); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + subpicture_priv = subpicture->privData; + pipe_surface_reference(&subpicture_priv->sfc, NULL); + FREE(subpicture_priv); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(palette); + + /* We don't support paletted subpictures */ + return BadMatch; +} + +PUBLIC +Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture, + short subx, short suby, unsigned short subw, unsigned short subh, + short surfx, short surfy, unsigned short surfw, unsigned short surfh) +{ + XvMCSurfacePrivate *surface_priv; + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface); + + assert(dpy); + + if (!target_surface) + return XvMCBadSurface; + + if (!subpicture) + return XvMCBadSubpicture; + + if (target_surface->context_id != subpicture->context_id) + return BadMatch; + + /* TODO: Verify against subpicture independent scaling */ + + surface_priv = target_surface->privData; + subpicture_priv = subpicture->privData; + + /* TODO: Assert rects are within bounds? Or clip? */ + + surface_priv->subpicture = subpicture; + surface_priv->subx = subx; + surface_priv->suby = suby; + surface_priv->subw = subw; + surface_priv->subh = subh; + surface_priv->surfx = surfx; + surface_priv->surfy = surfy; + surface_priv->surfw = surfw; + surface_priv->surfh = surfh; + subpicture_priv->surface = target_surface; + + return Success; +} + +PUBLIC +Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface, + XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh, + short surfx, short surfy, unsigned short surfw, unsigned short surfh) +{ + assert(dpy); + + if (!source_surface || !target_surface) + return XvMCBadSurface; + + if (!subpicture) + return XvMCBadSubpicture; + + if (source_surface->context_id != subpicture->context_id) + return BadMatch; + + if (source_surface->context_id != subpicture->context_id) + return BadMatch; + + /* TODO: Assert rects are within bounds? Or clip? */ + + return Success; +} + +PUBLIC +Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(status); + + /* TODO */ + *status = 0; + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c new file mode 100644 index 00000000000..d7285a478fb --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -0,0 +1,525 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <X11/Xlibint.h> +#include <vl_winsys.h> +#include <pipe/p_video_context.h> +#include <pipe/p_video_state.h> +#include <pipe/p_state.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include <util/u_math.h> +#include "xvmc_private.h" + +static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type) +{ + if (xvmc_mb_type & XVMC_MB_TYPE_INTRA) + return PIPE_MPEG12_MACROBLOCK_TYPE_INTRA; + if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD) + return PIPE_MPEG12_MACROBLOCK_TYPE_FWD; + if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD) + return PIPE_MPEG12_MACROBLOCK_TYPE_BKWD; + if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) + return PIPE_MPEG12_MACROBLOCK_TYPE_BI; + + assert(0); + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized mb type 0x%08X.\n", xvmc_mb_type); + + return -1; +} + +static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic) +{ + switch (xvmc_pic) { + case XVMC_TOP_FIELD: + return PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP; + case XVMC_BOTTOM_FIELD: + return PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM; + case XVMC_FRAME_PICTURE: + return PIPE_MPEG12_PICTURE_TYPE_FRAME; + default: + assert(0); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic); + + return -1; +} + +static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, unsigned int xvmc_picture_structure) +{ + switch (xvmc_motion_type) { + case XVMC_PREDICTION_FRAME: + if (xvmc_picture_structure == XVMC_FRAME_PICTURE) + return PIPE_MPEG12_MOTION_TYPE_FRAME; + else + return PIPE_MPEG12_MOTION_TYPE_16x8; + break; + case XVMC_PREDICTION_FIELD: + return PIPE_MPEG12_MOTION_TYPE_FIELD; + case XVMC_PREDICTION_DUAL_PRIME: + return PIPE_MPEG12_MOTION_TYPE_DUALPRIME; + default: + assert(0); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized motion type 0x%08X (with picture structure 0x%08X).\n", xvmc_motion_type, xvmc_picture_structure); + + return -1; +} + +#if 0 +static bool +CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned int height, + struct pipe_surface **backbuffer) +{ + struct pipe_video_context *vpipe; + struct pipe_resource template; + struct pipe_resource *tex; + + assert(vctx); + + vpipe = vctx->vpipe; + + if (*backbuffer) { + if ((*backbuffer)->width != width || (*backbuffer)->height != height) + pipe_surface_reference(backbuffer, NULL); + else + return true; + } + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + template.format = vctx->vscreen->format; + template.last_level = 0; + template.width0 = width; + template.height0 = height; + template.depth0 = 1; + template.usage = PIPE_USAGE_DEFAULT; + template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE; + template.flags = 0; + + tex = vpipe->screen->resource_create(vpipe->screen, &template); + if (!tex) + return false; + + *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0, + template.bind); + pipe_resource_reference(&tex, NULL); + + if (!*backbuffer) + return false; + + /* Clear the backbuffer in case the video doesn't cover the whole window */ + /* FIXME: Need to clear every time a frame moves and leaves dirty rects */ + vpipe->surface_fill(vpipe, *backbuffer, 0, 0, width, height, 0); + + return true; +} +#endif + +static void +MacroBlocksToPipe(struct pipe_screen *screen, + unsigned int xvmc_picture_structure, + const XvMCMacroBlockArray *xvmc_macroblocks, + const XvMCBlockArray *xvmc_blocks, + unsigned int first_macroblock, + unsigned int num_macroblocks, + struct pipe_mpeg12_macroblock *pipe_macroblocks) +{ + unsigned int i, j, k, l; + XvMCMacroBlock *xvmc_mb; + + assert(xvmc_macroblocks); + assert(xvmc_blocks); + assert(pipe_macroblocks); + assert(num_macroblocks); + + xvmc_mb = xvmc_macroblocks->macro_blocks + first_macroblock; + + for (i = 0; i < num_macroblocks; ++i) { + pipe_macroblocks->base.codec = PIPE_VIDEO_CODEC_MPEG12; + pipe_macroblocks->mbx = xvmc_mb->x; + pipe_macroblocks->mby = xvmc_mb->y; + pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type); + if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA) + pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_picture_structure); + /* Get rid of Valgrind 'undefined' warnings */ + else + pipe_macroblocks->mo_type = -1; + pipe_macroblocks->dct_type = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ? + PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME; + + for (j = 0; j < 2; ++j) + for (k = 0; k < 2; ++k) + for (l = 0; l < 2; ++l) + pipe_macroblocks->pmv[j][k][l] = xvmc_mb->PMV[j][k][l]; + + pipe_macroblocks->mvfs[0][0] = xvmc_mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD; + pipe_macroblocks->mvfs[0][1] = xvmc_mb->motion_vertical_field_select & XVMC_SELECT_FIRST_BACKWARD; + pipe_macroblocks->mvfs[1][0] = xvmc_mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD; + pipe_macroblocks->mvfs[1][1] = xvmc_mb->motion_vertical_field_select & XVMC_SELECT_SECOND_BACKWARD; + + pipe_macroblocks->cbp = xvmc_mb->coded_block_pattern; + pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; + + ++pipe_macroblocks; + ++xvmc_mb; + } +} + +PUBLIC +Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) +{ + XvMCContextPrivate *context_priv; + struct pipe_video_context *vpipe; + XvMCSurfacePrivate *surface_priv; + struct pipe_resource template; + struct pipe_resource *vsfc_tex; + struct pipe_surface surf_template; + struct pipe_surface *vsfc; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); + + assert(dpy); + + if (!context) + return XvMCBadContext; + if (!surface) + return XvMCBadSurface; + + context_priv = context->privData; + vpipe = context_priv->vctx->vpipe; + + surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); + if (!surface_priv) + return BadAlloc; + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + template.format = (enum pipe_format)vpipe->get_param(vpipe, PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT); + template.last_level = 0; + if (vpipe->is_format_supported(vpipe, template.format, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, + PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) { + template.width0 = context->width; + template.height0 = context->height; + } + else { + assert(vpipe->is_format_supported(vpipe, template.format, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, + PIPE_TEXTURE_GEOM_NON_SQUARE)); + template.width0 = util_next_power_of_two(context->width); + template.height0 = util_next_power_of_two(context->height); + } + template.depth0 = 1; + template.usage = PIPE_USAGE_DEFAULT; + template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + template.flags = 0; + vsfc_tex = vpipe->screen->resource_create(vpipe->screen, &template); + if (!vsfc_tex) { + FREE(surface_priv); + return BadAlloc; + } + + memset(&surf_template, 0, sizeof(surf_template)); + surf_template.format = vsfc_tex->format; + surf_template.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + vsfc = vpipe->create_surface(vpipe, vsfc_tex, &surf_template); + pipe_resource_reference(&vsfc_tex, NULL); + if (!vsfc) { + FREE(surface_priv); + return BadAlloc; + } + + surface_priv->pipe_vsfc = vsfc; + surface_priv->context = context; + + surface->surface_id = XAllocID(dpy); + surface->context_id = context->context_id; + surface->surface_type_id = context->surface_type_id; + surface->width = context->width; + surface->height = context->height; + surface->privData = surface_priv; + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure, + XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface, + unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock, + XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks +) +{ + struct pipe_video_context *vpipe; + struct pipe_surface *t_vsfc; + struct pipe_surface *p_vsfc; + struct pipe_surface *f_vsfc; + XvMCContextPrivate *context_priv; + XvMCSurfacePrivate *target_surface_priv; + XvMCSurfacePrivate *past_surface_priv; + XvMCSurfacePrivate *future_surface_priv; + struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks]; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p.\n", target_surface); + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + if (!target_surface || !target_surface->privData) + return XvMCBadSurface; + + if (picture_structure != XVMC_TOP_FIELD && + picture_structure != XVMC_BOTTOM_FIELD && + picture_structure != XVMC_FRAME_PICTURE) + return BadValue; + /* Bkwd pred equivalent to fwd (past && !future) */ + if (future_surface && !past_surface) + return BadMatch; + + assert(context->context_id == target_surface->context_id); + assert(!past_surface || context->context_id == past_surface->context_id); + assert(!future_surface || context->context_id == future_surface->context_id); + + assert(macroblocks); + assert(blocks); + + assert(macroblocks->context_id == context->context_id); + assert(blocks->context_id == context->context_id); + + assert(flags == 0 || flags == XVMC_SECOND_FIELD); + + target_surface_priv = target_surface->privData; + past_surface_priv = past_surface ? past_surface->privData : NULL; + future_surface_priv = future_surface ? future_surface->privData : NULL; + + assert(target_surface_priv->context == context); + assert(!past_surface || past_surface_priv->context == context); + assert(!future_surface || future_surface_priv->context == context); + + context_priv = context->privData; + vpipe = context_priv->vctx->vpipe; + + t_vsfc = target_surface_priv->pipe_vsfc; + p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL; + f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL; + + MacroBlocksToPipe(vpipe->screen, picture_structure, macroblocks, blocks, first_macroblock, + num_macroblocks, pipe_macroblocks); + + vpipe->set_decode_target(vpipe, t_vsfc); + vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks, + &pipe_macroblocks->base, &target_surface_priv->render_fence); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); + + return Success; +} + +PUBLIC +Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + return Success; +} + +PUBLIC +Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + return Success; +} + +PUBLIC +Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, + short srcx, short srcy, unsigned short srcw, unsigned short srch, + short destx, short desty, unsigned short destw, unsigned short desth, + int flags) +{ + static int dump_window = -1; + + struct pipe_video_context *vpipe; + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + XvMCContext *context; + struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch}; + struct pipe_video_rect dst_rect = {destx, desty, destw, desth}; + struct pipe_surface *drawable_surface; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + context = surface_priv->context; + context_priv = context->privData; + + drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable); + if (!drawable_surface) + return BadDrawable; + + assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); + assert(srcx + srcw - 1 < surface->width); + assert(srcy + srch - 1 < surface->height); + /* + * Some apps (mplayer) hit these asserts because they call + * this function after the window has been resized by the WM + * but before they've handled the corresponding XEvent and + * know about the new dimensions. The output should be clipped + * until the app updates destw and desth. + */ + /* + assert(destx + destw - 1 < drawable_surface->width); + assert(desty + desth - 1 < drawable_surface->height); + */ + + subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; + vpipe = context_priv->vctx->vpipe; + +#if 0 + if (!CreateOrResizeBackBuffer(context_priv->vctx, width, height, &context_priv->backbuffer)) + return BadAlloc; +#endif + + if (subpicture_priv) { + struct pipe_video_rect src_rect = {surface_priv->subx, surface_priv->suby, surface_priv->subw, surface_priv->subh}; + struct pipe_video_rect dst_rect = {surface_priv->surfx, surface_priv->surfy, surface_priv->surfw, surface_priv->surfh}; + struct pipe_video_rect *src_rects[1] = {&src_rect}; + struct pipe_video_rect *dst_rects[1] = {&dst_rect}; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); + + assert(subpicture_priv->surface == surface); + vpipe->set_picture_layers(vpipe, &subpicture_priv->sfc, src_rects, dst_rects, 1); + + surface_priv->subpicture = NULL; + subpicture_priv->surface = NULL; + } + else + vpipe->set_picture_layers(vpipe, NULL, NULL, NULL, 0); + + vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect, + drawable_surface, &dst_rect, &surface_priv->disp_fence); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); + + vpipe->screen->flush_frontbuffer + ( + vpipe->screen, + drawable_surface->texture, + 0, 0, + vl_contextprivate_get(context_priv->vctx, drawable_surface) + ); + + pipe_surface_reference(&drawable_surface, NULL); + + if(dump_window == -1) { + dump_window = debug_get_num_option("XVMC_DUMP", 0); + } + + if(dump_window) { + static unsigned int framenum = 0; + char cmd[256]; + sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); + system(cmd); + } + + XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + assert(status); + + *status = 0; + + return Success; +} + +PUBLIC +Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface) +{ + XvMCSurfacePrivate *surface_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + pipe_surface_reference(&surface_priv->pipe_vsfc, NULL); + FREE(surface_priv); + surface->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCHideSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + /* No op, only for overlaid rendering */ + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore new file mode 100644 index 00000000000..9a8e05d9472 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore @@ -0,0 +1,6 @@ +test_context +test_surface +test_subpicture +test_blocks +test_rendering +xvmc_bench diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/Makefile b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile new file mode 100644 index 00000000000..88b03763563 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile @@ -0,0 +1,31 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBS = -lXvMCW -lXvMC -lXv -lX11 + +############################################# + +.PHONY: default clean + +default: test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench + +test_context: test_context.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_surface: test_surface.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_subpicture: test_subpicture.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_blocks: test_blocks.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_rendering: test_rendering.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +xvmc_bench: xvmc_bench.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + $(RM) -rf *.o test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c new file mode 100644 index 00000000000..994e3ca4d14 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c @@ -0,0 +1,111 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int min_required_blocks = 1, min_required_macroblocks = 1; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray blocks = {0}; + XvMCMacroBlockArray macroblocks = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + + /* Test NULL context */ + assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); + /* Test 0 blocks */ + assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); + /* Test context id assigned and correct */ + assert(blocks.context_id == context.context_id); + /* Test number of blocks assigned and correct */ + assert(blocks.num_blocks == min_required_blocks); + /* Test block pointer valid */ + assert(blocks.blocks != NULL); + /* Test NULL context */ + assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); + /* Test 0 macroblocks */ + assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); + /* Test context id assigned and correct */ + assert(macroblocks.context_id == context.context_id); + /* Test macroblock pointer valid */ + assert(macroblocks.macro_blocks != NULL); + /* Test valid params */ + assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); + /* Test valid params */ + assert(XvMCDestroyBlocks(display, &blocks) == Success); + + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c new file mode 100644 index 00000000000..3da957c9330 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c @@ -0,0 +1,119 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + /* Test NULL context */ + /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); + /* Test invalid port */ + /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */ + assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); + /* Test invalid surface */ + assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch); + /* Test invalid flags */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); + /* Test huge width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); + /* Test huge height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test valid params */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + /* Test context id assigned */ + assert(context.context_id != 0); + /* Test surface type id assigned and correct */ + assert(context.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(context.width == width && context.height == height); + /* Test port assigned and correct */ + assert(context.port == port_num); + /* Test flags assigned and correct */ + assert(context.flags == XVMC_DIRECT); + /* Test NULL context */ + assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); + /* Test valid params */ + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1 && context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c new file mode 100644 index 00000000000..6058783a798 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c @@ -0,0 +1,317 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <error.h> +#include "testlib.h" + +#define BLOCK_WIDTH 8 +#define BLOCK_HEIGHT 8 +#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) +#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) +#define BLOCKS_PER_MACROBLOCK 6 + +#define INPUT_WIDTH 16 +#define INPUT_HEIGHT 16 +#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) +#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) +#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) + +#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH +#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT +#define DEFAULT_ACCEPTABLE_ERR 0.01 + +void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt); +void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal); + +void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt) +{ + int fail = 0; + int i; + + *output_width = DEFAULT_OUTPUT_WIDTH; + *output_height = DEFAULT_OUTPUT_WIDTH; + *acceptable_error = DEFAULT_ACCEPTABLE_ERR; + *prompt = 1; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-w")) + { + if (sscanf(argv[++i], "%u", output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-h")) + { + if (sscanf(argv[++i], "%u", output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-e")) + { + if (sscanf(argv[++i], "%lf", acceptable_error) != 1) + fail = 1; + } + else if (strcmp(argv[i], "-n")) + *prompt = 0; + else + fail = 1; + } + + if (fail) + error + ( + 1, 0, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-w <width>\tOutput width\n" + "\t-h <height>\tOutput height\n" + "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n" + "\t-n\tDon't prompt for quit\n", + argv[0] + ); +} + +void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal) +{ + unsigned int x, y; + unsigned int range = stop - start; + + if (horizontal) + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) + block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); + } + else + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) + block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1))); + } +} + +int main(int argc, char **argv) +{ + unsigned int output_width; + unsigned int output_height; + double acceptable_error; + int prompt; + Display *display; + Window root, window; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + int mbx, mby, bx, by; + XvMCMacroBlock *mb; + short *blocks; + int quit = 0; + + ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + INPUT_WIDTH, + INPUT_HEIGHT, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); + + mb = mb_array.macro_blocks; + blocks = block_array.blocks; + + for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) + for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) + { + mb->x = mbx; + mb->y = mby; + mb->macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb->dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; + mb->coded_block_pattern = 0x3F; + + mb++; + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) + { + const int start = 16, stop = 235, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + } + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) + { + const int start = 16, stop = 240, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + } + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + /* Test NULL context */ + assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); + /* Test NULL surface */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); + /* Test bad picture structure */ + assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); + /* Test valid params */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); + + /* Test NULL surface */ + assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); + /* Test bad window */ + /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ + /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ + + if (prompt) + { + puts("Press any button to quit..."); + + while (!quit) + { + if (XPending(display) > 0) + { + XEvent event; + + XNextEvent(display, &event); + + switch (event.type) + { + case Expose: + { + /* Test valid params */ + assert + ( + XvMCPutSurface + ( + display, &surface, window, + 0, 0, INPUT_WIDTH, INPUT_HEIGHT, + 0, 0, output_width, output_height, + XVMC_FRAME_PICTURE + ) == Success + ); + break; + } + case KeyPress: + { + quit = 1; + break; + } + } + } + } + } + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c new file mode 100644 index 00000000000..20d0907a07f --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include <stdio.h> +#include "testlib.h" + +static void PrintGUID(const char *guid) +{ + int i; + printf("\tguid: "); + for (i = 0; i < 4; ++i) + printf("%C,", guid[i] == 0 ? '0' : guid[i]); + for (; i < 15; ++i) + printf("%x,", (unsigned char)guid[i]); + printf("%x\n", (unsigned int)guid[15]); +} + +static void PrintComponentOrder(const char *co) +{ + int i; + printf("\tcomponent_order:\n\t "); + for (i = 0; i < 4; ++i) + printf("%C,", co[i] == 0 ? '0' : co[i]); + for (; i < 31; ++i) + printf("%x,", (unsigned int)co[i]); + printf("%x\n", (unsigned int)co[31]); +} + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + const unsigned int subpic_width = 16, subpic_height = 16; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvImageFormatValues *subpics; + int num_subpics; + XvMCSubpicture subpicture = {0}; + int i; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + + subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics); + assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0)); + + for (i = 0; i < num_subpics; ++i) + { + printf("Subpicture %d:\n", i); + printf("\tid: 0x%08x\n", subpics[i].id); + printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown")); + printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown")); + PrintGUID(subpics[i].guid); + printf("\tbpp: %u\n", subpics[i].bits_per_pixel); + printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown")); + printf("\tnum_planes: %u\n", subpics[i].num_planes); + + if (subpics[i].type == XvRGB) + { + printf("\tdepth: %u\n", subpics[i].depth); + printf("\tred_mask: 0x%08x\n", subpics[i].red_mask); + printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask); + printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask); + } + else if (subpics[i].type == XvYUV) + { + printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits); + printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits); + printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits); + printf("\thorz_y_period: %u\n", subpics[i].horz_y_period); + printf("\thorz_u_period: %u\n", subpics[i].horz_u_period); + printf("\thorz_v_period: %u\n", subpics[i].horz_v_period); + printf("\tvert_y_period: %u\n", subpics[i].vert_y_period); + printf("\tvert_u_period: %u\n", subpics[i].vert_u_period); + printf("\tvert_v_period: %u\n", subpics[i].vert_v_period); + } + PrintComponentOrder(subpics[i].component_order); + printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown")); + } + + if (num_subpics == 0) + { + printf("Subpictures not supported, nothing to test.\n"); + return 0; + } + + /* Test NULL context */ + assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext); + /* Test NULL subpicture */ + assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture); + /* Test invalid subpicture */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch); + /* Test huge width */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue); + /* Test huge height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue); + for (i = 0; i < num_subpics; ++i) + { + /* Test valid params */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success); + /* Test subpicture id assigned */ + assert(subpicture.subpicture_id != 0); + /* Test context id assigned and correct */ + assert(subpicture.context_id == context.context_id); + /* Test subpicture type id assigned and correct */ + assert(subpicture.xvimage_id == subpics[i].id); + /* Test width & height assigned and correct */ + assert(subpicture.width == width && subpicture.height == height); + /* Test no palette support */ + assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0); + /* Test valid params */ + assert(XvMCDestroySubpicture(display, &subpicture) == Success); + } + /* Test NULL surface */ + assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture); + + assert(XvMCDestroyContext(display, &context) == Success); + + XFree(subpics); + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c new file mode 100644 index 00000000000..b65eb265c0a --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + + /* Test NULL context */ + assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext); + /* Test NULL surface */ + assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); + /* Test valid params */ + assert(XvMCCreateSurface(display, &context, &surface) == Success); + /* Test surface id assigned */ + assert(surface.surface_id != 0); + /* Test context id assigned and correct */ + assert(surface.context_id == context.context_id); + /* Test surface type id assigned and correct */ + assert(surface.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(surface.width == width && surface.height == height); + /* Test valid params */ + assert(XvMCDestroySurface(display, &surface) == Success); + /* Test NULL surface */ + assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface); + + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c new file mode 100644 index 00000000000..142c09bb590 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c @@ -0,0 +1,146 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "testlib.h" +#include <stdio.h> + +/* +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) +{ + fputs(doc_string, stderr); + if (!pred) + fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); + else + fputs(" PASS!\n", stderr); +} +*/ + +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +) +{ + unsigned int found_port = 0; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + int ev_base, err_base; + unsigned int i, j, k, l; + + if (!XvMCQueryExtension(display, &ev_base, &err_base)) + return 0; + if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) + return 0; + + for (i = 0; i < num_adaptors && !found_port; ++i) + { + if (adaptor_info[i].type & XvImageMask) + { + XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); + + if (surface_info) + { + for (j = 0; j < num_types && !found_port; ++j) + { + if + ( + surface_info[j].chroma_format == chroma_format && + surface_info[j].max_width >= width && + surface_info[j].max_height >= height + ) + { + for (k = 0; k < num_mc_types && !found_port; ++k) + { + if (surface_info[j].mc_type == mc_types[k]) + { + for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) + { + if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) + { + *port_id = adaptor_info[i].base_id + l; + *surface_type_id = surface_info[j].surface_type_id; + *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; + *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; + found_port = 1; + } + } + } + } + } + } + + XFree(surface_info); + } + } + } + + XvFreeAdaptorInfo(adaptor_info); + + return found_port; +} + +unsigned int align(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +/* From the glibc manual */ +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) + { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) + { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* + * Compute the time remaining to wait. + * tv_usec is certainly positive. + */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h new file mode 100644 index 00000000000..0438e52928b --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef testlib_h +#define testlib_h + +/* +#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__) + +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); +*/ + +#include <sys/time.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> + +/* + * display: IN A valid X display + * width, height: IN Surface size that the port must display + * chroma_format: IN Chroma format that the port must display + * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned + * port_id: OUT Your port's ID + * surface_type_id: OUT Your port's surface ID + * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey + * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks + */ +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +); + +unsigned int align(unsigned int value, unsigned int alignment); + +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); + +#endif diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c new file mode 100644 index 00000000000..bf94d856234 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c @@ -0,0 +1,300 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <error.h> +#include <sys/time.h> +#include "testlib.h" + +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define BLOCKS_PER_MACROBLOCK 6 + +#define DEFAULT_INPUT_WIDTH 720 +#define DEFAULT_INPUT_HEIGHT 480 +#define DEFAULT_REPS 100 + +#define PIPELINE_STEP_MC 1 +#define PIPELINE_STEP_CSC 2 +#define PIPELINE_STEP_SWAP 4 + +#define MB_TYPE_I 1 +#define MB_TYPE_P 2 +#define MB_TYPE_B 4 + +struct Config +{ + unsigned int input_width; + unsigned int input_height; + unsigned int output_width; + unsigned int output_height; + unsigned int pipeline; + unsigned int mb_types; + unsigned int reps; +}; + +void ParseArgs(int argc, char **argv, struct Config *config); + +void ParseArgs(int argc, char **argv, struct Config *config) +{ + int fail = 0; + int i; + + config->input_width = DEFAULT_INPUT_WIDTH; + config->input_height = DEFAULT_INPUT_HEIGHT; + config->output_width = 0; + config->output_height = 0; + config->pipeline = 0; + config->mb_types = 0; + config->reps = DEFAULT_REPS; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-iw")) + { + if (sscanf(argv[++i], "%u", &config->input_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ih")) + { + if (sscanf(argv[++i], "%u", &config->input_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ow")) + { + if (sscanf(argv[++i], "%u", &config->output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-oh")) + { + if (sscanf(argv[++i], "%u", &config->output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-p")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (!strcmp(token, "mc")) + config->pipeline |= PIPELINE_STEP_MC; + else if (!strcmp(token, "csc")) + config->pipeline |= PIPELINE_STEP_CSC; + else if (!strcmp(token, "swp")) + config->pipeline |= PIPELINE_STEP_SWAP; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-mb")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (strcmp(token, "i")) + config->mb_types |= MB_TYPE_I; + else if (strcmp(token, "p")) + config->mb_types |= MB_TYPE_P; + else if (strcmp(token, "b")) + config->mb_types |= MB_TYPE_B; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-r")) + { + if (sscanf(argv[++i], "%u", &config->reps) != 1) + fail = 1; + } + else + fail = 1; + } + + if (fail) + error + ( + 1, 0, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-iw <width>\tInput width\n" + "\t-ih <height>\tInput height\n" + "\t-ow <width>\tOutput width\n" + "\t-oh <height>\tOutput height\n" + "\t-p <pipeline>\tPipeline to test\n" + "\t-mb <mb type>\tMacroBlock types to use\n" + "\t-r <reps>\tRepetitions\n\n" + "\tPipeline steps: mc,csc,swap\n" + "\tMB types: i,p,b\n", + argv[0] + ); + + if (config->output_width == 0) + config->output_width = config->input_width; + if (config->output_height == 0) + config->output_height = config->input_height; + if (!config->pipeline) + config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP; + if (!config->mb_types) + config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B; +} + +int main(int argc, char **argv) +{ + struct Config config; + Display *display; + Window root, window; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + unsigned int mbw, mbh; + unsigned int mbx, mby; + unsigned int reps; + struct timeval start, stop, diff; + double diff_secs; + + ParseArgs(argc, argv, &config); + + mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; + mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + config.input_width, + config.input_height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + error(1, 0, "Error, unable to find a good port.\n"); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success); + + for (mby = 0; mby < mbh; ++mby) + for (mbx = 0; mbx < mbw; ++mbx) + { + mb_array.macro_blocks[mby * mbw + mbx].x = mbx; + mb_array.macro_blocks[mby * mbw + mbx].y = mby; + mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK; + mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F; + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + gettimeofday(&start, NULL); + + for (reps = 0; reps < config.reps; ++reps) + { + if (config.pipeline & PIPELINE_STEP_MC) + { + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success); + assert(XvMCFlushSurface(display, &surface) == Success); + } + if (config.pipeline & PIPELINE_STEP_CSC) + assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success); + } + + gettimeofday(&stop, NULL); + + timeval_subtract(&diff, &stop, &start); + diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0; + + printf("XvMC Benchmark\n"); + printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height); + printf("Pipeline: "); + if (config.pipeline & PIPELINE_STEP_MC) + printf("|mc|"); + if (config.pipeline & PIPELINE_STEP_CSC) + printf("|csc|"); + if (config.pipeline & PIPELINE_STEP_SWAP) + printf("|swap|"); + printf("\n"); + printf("Reps: %u\n", config.reps); + printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs); + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h new file mode 100644 index 00000000000..1e2dfb4223a --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h @@ -0,0 +1,102 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef xvmc_private_h +#define xvmc_private_h + +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> +#include <util/u_debug.h> + +#define BLOCK_SIZE_SAMPLES 64 +#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2) + +struct vl_context; +struct pipe_surface; +struct pipe_fence_handle; + +typedef struct +{ + struct vl_context *vctx; + struct pipe_surface *backbuffer; + unsigned short subpicture_max_width; + unsigned short subpicture_max_height; +} XvMCContextPrivate; + +typedef struct +{ + struct pipe_surface *pipe_vsfc; + struct pipe_fence_handle *render_fence; + struct pipe_fence_handle *disp_fence; + + /* The subpicture associated with this surface, if any. */ + XvMCSubpicture *subpicture; + short subx, suby; + unsigned short subw, subh; + short surfx, surfy; + unsigned short surfw, surfh; + + /* Some XvMC functions take a surface but not a context, + so we keep track of which context each surface belongs to. */ + XvMCContext *context; +} XvMCSurfacePrivate; + +typedef struct +{ + struct pipe_surface *sfc; + + /* The surface this subpicture is currently associated with, if any. */ + XvMCSurface *surface; + + /* Some XvMC functions take a subpicture but not a context, + so we keep track of which context each subpicture belongs to. */ + XvMCContext *context; +} XvMCSubpicturePrivate; + +#define XVMC_OUT 0 +#define XVMC_ERR 1 +#define XVMC_WARN 2 +#define XVMC_TRACE 3 +static INLINE void XVMC_MSG(unsigned int level, const char *fmt, ...) +{ + static boolean check_dbg_level = TRUE; + static unsigned int debug_level; + + if (check_dbg_level) { + debug_level = debug_get_num_option("XVMC_DEBUG", 0); + check_dbg_level = FALSE; + } + + if (level <= debug_level) { + va_list ap; + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +#endif /* xvmc_private_h */ diff --git a/src/gallium/targets/Makefile.va b/src/gallium/targets/Makefile.va new file mode 100644 index 00000000000..efb0a59522a --- /dev/null +++ b/src/gallium/targets/Makefile.va @@ -0,0 +1,62 @@ +# This makefile template is used to build "driver"_drv_video.so + +LIBNAME = lib$(LIBBASENAME).so +VA_LIB_GLOB= lib$(LIBBASENAME).*so* +VA_MAJOR = 0 +VA_MINOR = 3 +INCLUDES = -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/gallium/winsys/g3dvl \ + $(DRIVER_INCLUDES) +DEFINES = -DGALLIUM_TRACE -DVER_MAJOR=$(VA_MAJOR) -DVER_MINOR=$(VA_MINOR) $(DRIVER_DEFINES) +LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lva -lXext -lX11 -lm +STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/va/libvatracker.a + +# XXX: Hack, VA public funcs aren't exported +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) \ + $(TOP)/src/gallium/state_trackers/va/*.o + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +##### TARGETS ##### + +default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) + +$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(OBJECTS) $(PIPE_DRIVERS) $(STATE_TRACKER_LIB) $(TOP)/$(LIB_DIR)/gallium Makefile + $(MKLIB) -o $(LIBBASENAME) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(VA_MAJOR) -minor $(VA_MINOR) $(MKLIB_OPTIONS) \ + -install $(TOP)/$(LIB_DIR)/gallium \ + $(OBJECTS) $(STATE_TRACKER_LIB) $(PIPE_DRIVERS) $(LIBS) + +$(TOP)/$(LIB_DIR)/gallium: + mkdir -p $@ + +depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) \ + $(ASM_SOURCES) 2> /dev/null + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + +# Remove .o and backup files +clean: + -rm -f *.o *~ *.so $(SYMLINKS) + -rm -f depend depend.bak + +install: default + $(INSTALL) -d $(DESTDIR)$(VA_LIB_INSTALL_DIR) + $(MINSTALL) -m 755 $(TOP)/$(LIB_DIR)/gallium/$(VA_LIB_GLOB) $(DESTDIR)$(VA_LIB_INSTALL_DIR) + +include depend diff --git a/src/gallium/targets/Makefile.vdpau b/src/gallium/targets/Makefile.vdpau new file mode 100644 index 00000000000..2accbeb702e --- /dev/null +++ b/src/gallium/targets/Makefile.vdpau @@ -0,0 +1,62 @@ +# This makefile template is used to build libvdpau_g3dvl.so + +LIBBASENAME = vdpau_g3dvl +LIBNAME = lib$(LIBBASENAME).so +VDPAU_LIB_GLOB=lib$(LIBBASENAME).*so* +VDPAU_MAJOR = 1 +VDPAU_MINOR = 0 +INCLUDES = -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/winsys/g3dvl \ + $(DRIVER_INCLUDES) +DEFINES = -DGALLIUM_TRACE -DVER_MAJOR=$(VDPAU_MAJOR) -DVER_MINOR=$(VDPAU_MINOR) $(DRIVER_DEFINES) +LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lvdpau -lXext -lX11 -lm +STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/vdpau/libvdpautracker.a + +# XXX: Hack, VDPAU public funcs aren't exported if we link to libvdpautracker.a :( +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) \ + $(TOP)/src/gallium/state_trackers/vdpau/*.o + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +##### TARGETS ##### + +default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) + +$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(OBJECTS) $(PIPE_DRIVERS) $(STATE_TRACKER_LIB) $(TOP)/$(LIB_DIR)/gallium Makefile + $(MKLIB) -o $(LIBBASENAME) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(VDPAU_MAJOR) -minor $(VDPAU_MINOR) $(MKLIB_OPTIONS) \ + -install $(TOP)/$(LIB_DIR)/gallium \ + $(OBJECTS) $(STATE_TRACKER_LIB) $(PIPE_DRIVERS) $(LIBS) + +$(TOP)/$(LIB_DIR)/gallium: + mkdir -p $@ + +depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) \ + $(ASM_SOURCES) 2> /dev/null + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + +# Remove .o and backup files +clean: + -rm -f *.o *~ *.so $(SYMLINKS) + -rm -f depend depend.bak + +install: default + $(INSTALL) -d $(DESTDIR)$(VDPAU_LIB_INSTALL_DIR) + $(MINSTALL) -m 755 $(TOP)/$(LIB_DIR)/gallium/$(VDPAU_LIB_GLOB) $(DESTDIR)$(VDPAU_LIB_INSTALL_DIR) + +include depend diff --git a/src/gallium/targets/Makefile.xvmc b/src/gallium/targets/Makefile.xvmc new file mode 100644 index 00000000000..6abe7f6b062 --- /dev/null +++ b/src/gallium/targets/Makefile.xvmc @@ -0,0 +1,62 @@ +# This makefile template is used to build libXvMCg3dvl.so + +LIBNAME = lib$(LIBBASENAME).so +LIB_GLOB=lib$(LIBBASENAME).*so* +XVMC_MAJOR = 1 +XVMC_MINOR = 0 +INCLUDES = -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/gallium/winsys/g3dvl \ + $(DRIVER_INCLUDES) +DEFINES = -DGALLIUM_TRACE $(DRIVER_DEFINES) +LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lXv -lX11 -lm +STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/xorg/xvmc/libxvmctracker.a + +# XXX: Hack, XvMC public funcs aren't exported if we link to libxvmctracker.a :( +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) \ + $(TOP)/src/gallium/state_trackers/xorg/xvmc/*.o + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +##### TARGETS ##### + +default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) + +$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(OBJECTS) $(PIPE_DRIVERS) $(STATE_TRACKER_LIB) $(TOP)/$(LIB_DIR)/gallium Makefile + $(MKLIB) -o $(LIBBASENAME) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(XVMC_MAJOR) -minor $(XVMC_MINOR) $(MKLIB_OPTIONS) \ + -install $(TOP)/$(LIB_DIR)/gallium \ + $(OBJECTS) $(STATE_TRACKER_LIB) $(PIPE_DRIVERS) $(LIBS) + +$(TOP)/$(LIB_DIR)/gallium: + mkdir -p $@ + +depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) \ + $(ASM_SOURCES) 2> /dev/null + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + +# Remove .o and backup files +clean: + -rm -f *.o *~ *.so $(SYMLINKS) + -rm -f depend depend.bak + +install: default + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + $(MINSTALL) -m 755 $(TOP)/$(LIB_DIR)/gallium/$(LIB_GLOB) $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + +include depend diff --git a/src/gallium/targets/dri-nouveau/Makefile b/src/gallium/targets/dri-nouveau/Makefile index eb1ee859a00..26c927e0a81 100644 --- a/src/gallium/targets/dri-nouveau/Makefile +++ b/src/gallium/targets/dri-nouveau/Makefile @@ -11,6 +11,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nvc0/libnvc0.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a C_SOURCES = \ diff --git a/src/gallium/targets/va-r600/Makefile b/src/gallium/targets/va-r600/Makefile new file mode 100644 index 00000000000..03ca8edaf25 --- /dev/null +++ b/src/gallium/targets/va-r600/Makefile @@ -0,0 +1,26 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBBASENAME = r600_drv_video + +DRIVER_DEFINES = -DGALLIUM_SOFTPIPE +DRIVER_INCLUDES = + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/drivers/r600/libr600.a \ + $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \ + $(TOP)/src/gallium/winsys/r600/drm/libr600winsys.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + target.c \ + $(COMMON_GALLIUM_SOURCES) \ + $(DRIVER_SOURCES) + +DRIVER_LIBS = $(shell pkg-config libdrm_radeon --libs) -lXfixes + +include ../Makefile.va + +symlinks: diff --git a/src/gallium/targets/va-r600/target.c b/src/gallium/targets/va-r600/target.c new file mode 100644 index 00000000000..8753e2bab17 --- /dev/null +++ b/src/gallium/targets/va-r600/target.c @@ -0,0 +1,24 @@ +#include "state_tracker/drm_driver.h" +#include "target-helpers/inline_debug_helper.h" +#include "r600/drm/r600_drm_public.h" +#include "r600/r600_public.h" + +static struct pipe_screen *create_screen(int fd) +{ + struct radeon *radeon; + struct pipe_screen *screen; + + radeon = r600_drm_winsys_create(fd); + if (!radeon) + return NULL; + + screen = r600_screen_create(radeon); + if (!screen) + return NULL; + + screen = debug_screen_wrap(screen); + + return screen; +} + +DRM_DRIVER_DESCRIPTOR("r600", "radeon", create_screen) diff --git a/src/gallium/targets/va-softpipe/Makefile b/src/gallium/targets/va-softpipe/Makefile new file mode 100644 index 00000000000..a58df36a966 --- /dev/null +++ b/src/gallium/targets/va-softpipe/Makefile @@ -0,0 +1,21 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBBASENAME = softpipe_drv_video + +DRIVER_DEFINES = -DGALLIUM_SOFTPIPE +DRIVER_INCLUDES = + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + $(TOP)/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c + +DRIVER_LIBS = + +include ../Makefile.va + +symlinks: diff --git a/src/gallium/targets/vdpau-softpipe/Makefile b/src/gallium/targets/vdpau-softpipe/Makefile new file mode 100644 index 00000000000..29dea50e7fb --- /dev/null +++ b/src/gallium/targets/vdpau-softpipe/Makefile @@ -0,0 +1,19 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +DRIVER_DEFINES = -DGALLIUM_SOFTPIPE +DRIVER_INCLUDES = + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + $(TOP)/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c + +DRIVER_LIBS = + +include ../Makefile.vdpau + +symlinks: diff --git a/src/gallium/targets/xvmc-nouveau/Makefile b/src/gallium/targets/xvmc-nouveau/Makefile new file mode 100644 index 00000000000..4384eeaeadf --- /dev/null +++ b/src/gallium/targets/xvmc-nouveau/Makefile @@ -0,0 +1,23 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBBASENAME = XvMCnouveau + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \ + $(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ + $(TOP)/src/gallium/drivers/nv50/libnv50.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + $(COMMON_GALLIUM_SOURCES) \ + $(DRIVER_SOURCES) + +DRIVER_LIBS = $(shell pkg-config libdrm_nouveau --libs) -lXfixes + +include ../Makefile.xvmc + +symlinks: diff --git a/src/gallium/targets/xvmc-r600/Makefile b/src/gallium/targets/xvmc-r600/Makefile new file mode 100644 index 00000000000..62e47b53851 --- /dev/null +++ b/src/gallium/targets/xvmc-r600/Makefile @@ -0,0 +1,23 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBBASENAME = XvMCr600 + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/drivers/r600/libr600.a \ + $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \ + $(TOP)/src/gallium/winsys/r600/drm/libr600winsys.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + target.c \ + $(COMMON_GALLIUM_SOURCES) \ + $(DRIVER_SOURCES) + +DRIVER_LIBS = $(shell pkg-config libdrm_radeon --libs) -lXfixes + +include ../Makefile.xvmc + +symlinks: diff --git a/src/gallium/targets/xvmc-r600/target.c b/src/gallium/targets/xvmc-r600/target.c new file mode 100644 index 00000000000..8753e2bab17 --- /dev/null +++ b/src/gallium/targets/xvmc-r600/target.c @@ -0,0 +1,24 @@ +#include "state_tracker/drm_driver.h" +#include "target-helpers/inline_debug_helper.h" +#include "r600/drm/r600_drm_public.h" +#include "r600/r600_public.h" + +static struct pipe_screen *create_screen(int fd) +{ + struct radeon *radeon; + struct pipe_screen *screen; + + radeon = r600_drm_winsys_create(fd); + if (!radeon) + return NULL; + + screen = r600_screen_create(radeon); + if (!screen) + return NULL; + + screen = debug_screen_wrap(screen); + + return screen; +} + +DRM_DRIVER_DESCRIPTOR("r600", "radeon", create_screen) diff --git a/src/gallium/targets/xvmc-softpipe/Makefile b/src/gallium/targets/xvmc-softpipe/Makefile new file mode 100644 index 00000000000..5b60bede589 --- /dev/null +++ b/src/gallium/targets/xvmc-softpipe/Makefile @@ -0,0 +1,21 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBBASENAME = XvMCsoftpipe + +DRIVER_DEFINES = -DGALLIUM_SOFTPIPE +DRIVER_INCLUDES = + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +C_SOURCES = \ + $(TOP)/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c + +DRIVER_LIBS = + +include ../Makefile.xvmc + +symlinks: diff --git a/src/gallium/tests/python/retrace/README b/src/gallium/tests/python/retrace/README deleted file mode 100644 index 822cd114044..00000000000 --- a/src/gallium/tests/python/retrace/README +++ /dev/null @@ -1,17 +0,0 @@ -This is an application written in python to replay the traces captured by the - trace pipe driver. - - -To use it follow the instructions in src/gallium/drivers/trace/README and -src/gallium/state_trackers/python/README, and then do - - python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace - - -This is still work in progress: -- not everything is captured/replayed - - surface/textures contents -- any tiny error will result in a crash - --- -Jose Fonseca <[email protected]> diff --git a/src/gallium/tests/python/retrace/format.py b/src/gallium/tests/python/retrace/format.py deleted file mode 100755 index a4285bfe075..00000000000 --- a/src/gallium/tests/python/retrace/format.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -import sys - - -class Formatter: - '''Plain formatter''' - - def __init__(self, stream): - self.stream = stream - - def text(self, text): - self.stream.write(text) - - def newline(self): - self.text('\n') - - def function(self, name): - self.text(name) - - def variable(self, name): - self.text(name) - - def literal(self, value): - self.text(str(value)) - - def address(self, addr): - self.text(str(addr)) - - -class AnsiFormatter(Formatter): - '''Formatter for plain-text files which outputs ANSI escape codes. See - http://en.wikipedia.org/wiki/ANSI_escape_code for more information - concerning ANSI escape codes. - ''' - - _csi = '\33[' - - _normal = '0m' - _bold = '1m' - _italic = '3m' - _red = '31m' - _green = '32m' - _blue = '34m' - - def _escape(self, code): - self.text(self._csi + code) - - def function(self, name): - self._escape(self._bold) - Formatter.function(self, name) - self._escape(self._normal) - - def variable(self, name): - self._escape(self._italic) - Formatter.variable(self, name) - self._escape(self._normal) - - def literal(self, value): - self._escape(self._blue) - Formatter.literal(self, value) - self._escape(self._normal) - - def address(self, value): - self._escape(self._green) - Formatter.address(self, value) - self._escape(self._normal) - - -class WindowsConsoleFormatter(Formatter): - '''Formatter for the Windows Console. See - http://code.activestate.com/recipes/496901/ for more information. - ''' - - STD_INPUT_HANDLE = -10 - STD_OUTPUT_HANDLE = -11 - STD_ERROR_HANDLE = -12 - - FOREGROUND_BLUE = 0x01 - FOREGROUND_GREEN = 0x02 - FOREGROUND_RED = 0x04 - FOREGROUND_INTENSITY = 0x08 - BACKGROUND_BLUE = 0x10 - BACKGROUND_GREEN = 0x20 - BACKGROUND_RED = 0x40 - BACKGROUND_INTENSITY = 0x80 - - _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED - _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY - _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED - _red = FOREGROUND_RED | FOREGROUND_INTENSITY - _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY - _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY - - def __init__(self, stream): - Formatter.__init__(self, stream) - - if stream is sys.stdin: - nStdHandle = self.STD_INPUT_HANDLE - elif stream is sys.stdout: - nStdHandle = self.STD_OUTPUT_HANDLE - elif stream is sys.stderr: - nStdHandle = self.STD_ERROR_HANDLE - else: - nStdHandle = None - - if nStdHandle: - import ctypes - self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle) - else: - self.handle = None - - def _attribute(self, attr): - if self.handle: - import ctypes - ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr) - - def function(self, name): - self._attribute(self._bold) - Formatter.function(self, name) - self._attribute(self._normal) - - def variable(self, name): - self._attribute(self._italic) - Formatter.variable(self, name) - self._attribute(self._normal) - - def literal(self, value): - self._attribute(self._blue) - Formatter.literal(self, value) - self._attribute(self._normal) - - def address(self, value): - self._attribute(self._green) - Formatter.address(self, value) - self._attribute(self._normal) - - -def DefaultFormatter(stream): - if sys.platform in ('linux2', 'cygwin'): - return AnsiFormatter(stream) - elif sys.platform in ('win32',): - return WindowsConsoleFormatter(stream) - else: - return Formatter(stream) - diff --git a/src/gallium/tests/python/retrace/model.py b/src/gallium/tests/python/retrace/model.py deleted file mode 100755 index d4a079fb1e5..00000000000 --- a/src/gallium/tests/python/retrace/model.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -'''Trace data model.''' - - -import sys -import string -import format - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - - -class Node: - - def visit(self, visitor): - raise NotImplementedError - - def __str__(self): - stream = StringIO() - formatter = format.DefaultFormatter(stream) - pretty_printer = PrettyPrinter(formatter) - self.visit(pretty_printer) - return stream.getvalue() - - -class Literal(Node): - - def __init__(self, value): - self.value = value - - def visit(self, visitor): - visitor.visit_literal(self) - - -class NamedConstant(Node): - - def __init__(self, name): - self.name = name - - def visit(self, visitor): - visitor.visit_named_constant(self) - - -class Array(Node): - - def __init__(self, elements): - self.elements = elements - - def visit(self, visitor): - visitor.visit_array(self) - - -class Struct(Node): - - def __init__(self, name, members): - self.name = name - self.members = members - - def visit(self, visitor): - visitor.visit_struct(self) - - -class Pointer(Node): - - def __init__(self, address): - self.address = address - - def visit(self, visitor): - visitor.visit_pointer(self) - - -class Call: - - def __init__(self, no, klass, method, args, ret): - self.no = no - self.klass = klass - self.method = method - self.args = args - self.ret = ret - - def visit(self, visitor): - visitor.visit_call(self) - - -class Trace: - - def __init__(self, calls): - self.calls = calls - - def visit(self, visitor): - visitor.visit_trace(self) - - -class Visitor: - - def visit_literal(self, node): - raise NotImplementedError - - def visit_named_constant(self, node): - raise NotImplementedError - - def visit_array(self, node): - raise NotImplementedError - - def visit_struct(self, node): - raise NotImplementedError - - def visit_pointer(self, node): - raise NotImplementedError - - def visit_call(self, node): - raise NotImplementedError - - def visit_trace(self, node): - raise NotImplementedError - - -class PrettyPrinter: - - def __init__(self, formatter): - self.formatter = formatter - - def visit_literal(self, node): - if isinstance(node.value, basestring): - if len(node.value) >= 4096 or node.value.strip(string.printable): - self.formatter.text('...') - return - - self.formatter.literal('"' + node.value + '"') - return - - self.formatter.literal(repr(node.value)) - - def visit_named_constant(self, node): - self.formatter.literal(node.name) - - def visit_array(self, node): - self.formatter.text('{') - sep = '' - for value in node.elements: - self.formatter.text(sep) - value.visit(self) - sep = ', ' - self.formatter.text('}') - - def visit_struct(self, node): - self.formatter.text('{') - sep = '' - for name, value in node.members: - self.formatter.text(sep) - self.formatter.variable(name) - self.formatter.text(' = ') - value.visit(self) - sep = ', ' - self.formatter.text('}') - - def visit_pointer(self, node): - self.formatter.address(node.address) - - def visit_call(self, node): - self.formatter.text('%s ' % node.no) - if node.klass is not None: - self.formatter.function(node.klass + '::' + node.method) - else: - self.formatter.function(node.method) - self.formatter.text('(') - sep = '' - for name, value in node.args: - self.formatter.text(sep) - self.formatter.variable(name) - self.formatter.text(' = ') - value.visit(self) - sep = ', ' - self.formatter.text(')') - if node.ret is not None: - self.formatter.text(' = ') - node.ret.visit(self) - - def visit_trace(self, node): - for call in node.calls: - call.visit(self) - self.formatter.newline() - diff --git a/src/gallium/tests/python/retrace/parse.py b/src/gallium/tests/python/retrace/parse.py deleted file mode 100755 index b08d3686715..00000000000 --- a/src/gallium/tests/python/retrace/parse.py +++ /dev/null @@ -1,392 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -import sys -import xml.parsers.expat -import binascii -import optparse - -from model import * - - -ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) - - -class XmlToken: - - def __init__(self, type, name_or_data, attrs = None, line = None, column = None): - assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) - self.type = type - self.name_or_data = name_or_data - self.attrs = attrs - self.line = line - self.column = column - - def __str__(self): - if self.type == ELEMENT_START: - return '<' + self.name_or_data + ' ...>' - if self.type == ELEMENT_END: - return '</' + self.name_or_data + '>' - if self.type == CHARACTER_DATA: - return self.name_or_data - if self.type == EOF: - return 'end of file' - assert 0 - - -class XmlTokenizer: - """Expat based XML tokenizer.""" - - def __init__(self, fp, skip_ws = True): - self.fp = fp - self.tokens = [] - self.index = 0 - self.final = False - self.skip_ws = skip_ws - - self.character_pos = 0, 0 - self.character_data = '' - - self.parser = xml.parsers.expat.ParserCreate() - self.parser.StartElementHandler = self.handle_element_start - self.parser.EndElementHandler = self.handle_element_end - self.parser.CharacterDataHandler = self.handle_character_data - - def handle_element_start(self, name, attributes): - self.finish_character_data() - line, column = self.pos() - token = XmlToken(ELEMENT_START, name, attributes, line, column) - self.tokens.append(token) - - def handle_element_end(self, name): - self.finish_character_data() - line, column = self.pos() - token = XmlToken(ELEMENT_END, name, None, line, column) - self.tokens.append(token) - - def handle_character_data(self, data): - if not self.character_data: - self.character_pos = self.pos() - self.character_data += data - - def finish_character_data(self): - if self.character_data: - if not self.skip_ws or not self.character_data.isspace(): - line, column = self.character_pos - token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) - self.tokens.append(token) - self.character_data = '' - - def next(self): - size = 16*1024 - while self.index >= len(self.tokens) and not self.final: - self.tokens = [] - self.index = 0 - data = self.fp.read(size) - self.final = len(data) < size - data = data.rstrip('\0') - try: - self.parser.Parse(data, self.final) - except xml.parsers.expat.ExpatError, e: - #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: - if e.code == 3: - pass - else: - raise e - if self.index >= len(self.tokens): - line, column = self.pos() - token = XmlToken(EOF, None, None, line, column) - else: - token = self.tokens[self.index] - self.index += 1 - return token - - def pos(self): - return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber - - -class TokenMismatch(Exception): - - def __init__(self, expected, found): - self.expected = expected - self.found = found - - def __str__(self): - return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) - - - -class XmlParser: - """Base XML document parser.""" - - def __init__(self, fp): - self.tokenizer = XmlTokenizer(fp) - self.consume() - - def consume(self): - self.token = self.tokenizer.next() - - def match_element_start(self, name): - return self.token.type == ELEMENT_START and self.token.name_or_data == name - - def match_element_end(self, name): - return self.token.type == ELEMENT_END and self.token.name_or_data == name - - def element_start(self, name): - while self.token.type == CHARACTER_DATA: - self.consume() - if self.token.type != ELEMENT_START: - raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) - if self.token.name_or_data != name: - raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) - attrs = self.token.attrs - self.consume() - return attrs - - def element_end(self, name): - while self.token.type == CHARACTER_DATA: - self.consume() - if self.token.type != ELEMENT_END: - raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) - if self.token.name_or_data != name: - raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) - self.consume() - - def character_data(self, strip = True): - data = '' - while self.token.type == CHARACTER_DATA: - data += self.token.name_or_data - self.consume() - if strip: - data = data.strip() - return data - - -class TraceParser(XmlParser): - - def __init__(self, fp): - XmlParser.__init__(self, fp) - self.last_call_no = 0 - - def parse(self): - self.element_start('trace') - while self.token.type not in (ELEMENT_END, EOF): - call = self.parse_call() - self.handle_call(call) - if self.token.type != EOF: - self.element_end('trace') - - def parse_call(self): - attrs = self.element_start('call') - try: - no = int(attrs['no']) - except KeyError: - self.last_call_no += 1 - no = self.last_call_no - else: - self.last_call_no = no - klass = attrs['class'] - method = attrs['method'] - args = [] - ret = None - while self.token.type == ELEMENT_START: - if self.token.name_or_data == 'arg': - arg = self.parse_arg() - args.append(arg) - elif self.token.name_or_data == 'ret': - ret = self.parse_ret() - elif self.token.name_or_data == 'call': - # ignore nested function calls - self.parse_call() - else: - raise TokenMismatch("<arg ...> or <ret ...>", self.token) - self.element_end('call') - - return Call(no, klass, method, args, ret) - - def parse_arg(self): - attrs = self.element_start('arg') - name = attrs['name'] - value = self.parse_value() - self.element_end('arg') - - return name, value - - def parse_ret(self): - attrs = self.element_start('ret') - value = self.parse_value() - self.element_end('ret') - - return value - - def parse_value(self): - expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') - if self.token.type == ELEMENT_START: - if self.token.name_or_data in expected_tokens: - method = getattr(self, 'parse_' + self.token.name_or_data) - return method() - raise TokenMismatch(" or " .join(expected_tokens), self.token) - - def parse_null(self): - self.element_start('null') - self.element_end('null') - return Literal(None) - - def parse_bool(self): - self.element_start('bool') - value = int(self.character_data()) - self.element_end('bool') - return Literal(value) - - def parse_int(self): - self.element_start('int') - value = int(self.character_data()) - self.element_end('int') - return Literal(value) - - def parse_uint(self): - self.element_start('uint') - value = int(self.character_data()) - self.element_end('uint') - return Literal(value) - - def parse_float(self): - self.element_start('float') - value = float(self.character_data()) - self.element_end('float') - return Literal(value) - - def parse_enum(self): - self.element_start('enum') - name = self.character_data() - self.element_end('enum') - return NamedConstant(name) - - def parse_string(self): - self.element_start('string') - value = self.character_data() - self.element_end('string') - return Literal(value) - - def parse_bytes(self): - self.element_start('bytes') - value = binascii.a2b_hex(self.character_data()) - self.element_end('bytes') - return Literal(value) - - def parse_array(self): - self.element_start('array') - elems = [] - while self.token.type != ELEMENT_END: - elems.append(self.parse_elem()) - self.element_end('array') - return Array(elems) - - def parse_elem(self): - self.element_start('elem') - value = self.parse_value() - self.element_end('elem') - return value - - def parse_struct(self): - attrs = self.element_start('struct') - name = attrs['name'] - members = [] - while self.token.type != ELEMENT_END: - members.append(self.parse_member()) - self.element_end('struct') - return Struct(name, members) - - def parse_member(self): - attrs = self.element_start('member') - name = attrs['name'] - value = self.parse_value() - self.element_end('member') - - return name, value - - def parse_ptr(self): - self.element_start('ptr') - address = self.character_data() - self.element_end('ptr') - - return Pointer(address) - - def handle_call(self, call): - pass - - -class TraceDumper(TraceParser): - - def __init__(self, fp): - TraceParser.__init__(self, fp) - self.formatter = format.DefaultFormatter(sys.stdout) - self.pretty_printer = PrettyPrinter(self.formatter) - - def handle_call(self, call): - call.visit(self.pretty_printer) - self.formatter.newline() - - -class Main: - '''Common main class for all retrace command line utilities.''' - - def __init__(self): - pass - - def main(self): - optparser = self.get_optparser() - (options, args) = optparser.parse_args(sys.argv[1:]) - - if args: - for arg in args: - if arg.endswith('.gz'): - from gzip import GzipFile - stream = GzipFile(arg, 'rt') - elif arg.endswith('.bz2'): - from bz2 import BZ2File - stream = BZ2File(arg, 'rU') - else: - stream = open(arg, 'rt') - self.process_arg(stream, options) - else: - self.process_arg(stream, options) - - def get_optparser(self): - optparser = optparse.OptionParser( - usage="\n\t%prog [options] [traces] ...") - return optparser - - def process_arg(self, stream, options): - parser = TraceDumper(stream) - parser.parse() - - -if __name__ == '__main__': - Main().main() diff --git a/src/gallium/tests/python/retrace/parser.py b/src/gallium/tests/python/retrace/parser.py deleted file mode 100755 index bd47c9a6b06..00000000000 --- a/src/gallium/tests/python/retrace/parser.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -from parse import * - - -if __name__ == '__main__': - Main().main() diff --git a/src/gallium/tests/python/samples/gs.py b/src/gallium/tests/python/samples/gs.py deleted file mode 100644 index 936c0b3f33a..00000000000 --- a/src/gallium/tests/python/samples/gs.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2009 VMware -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -from gallium import * - - -def make_image(surface): - data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) - - import Image - outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) - return outimage - -def save_image(filename, surface): - outimage = make_image(surface) - outimage.save(filename, "PNG") - -def show_image(surface): - outimage = make_image(surface) - - import Tkinter as tk - from PIL import Image, ImageTk - root = tk.Tk() - - root.title('background image') - - image1 = ImageTk.PhotoImage(outimage) - w = image1.width() - h = image1.height() - x = 100 - y = 100 - root.geometry("%dx%d+%d+%d" % (w, h, x, y)) - panel1 = tk.Label(root, image=image1) - panel1.pack(side='top', fill='both', expand='yes') - panel1.image = image1 - root.mainloop() - - -def test(dev): - ctx = dev.context_create() - - width = 255 - height = 255 - minz = 0.0 - maxz = 1.0 - - # disabled blending/masking - blend = Blend() - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].colormask = PIPE_MASK_RGBA - ctx.set_blend(blend) - - # depth/stencil/alpha - depth_stencil_alpha = DepthStencilAlpha() - depth_stencil_alpha.depth.enabled = 1 - depth_stencil_alpha.depth.writemask = 1 - depth_stencil_alpha.depth.func = PIPE_FUNC_LESS - ctx.set_depth_stencil_alpha(depth_stencil_alpha) - - # rasterizer - rasterizer = Rasterizer() - rasterizer.front_winding = PIPE_WINDING_CW - rasterizer.cull_mode = PIPE_WINDING_NONE - rasterizer.scissor = 1 - ctx.set_rasterizer(rasterizer) - - # viewport - viewport = Viewport() - scale = FloatArray(4) - scale[0] = width / 2.0 - scale[1] = -height / 2.0 - scale[2] = (maxz - minz) / 2.0 - scale[3] = 1.0 - viewport.scale = scale - translate = FloatArray(4) - translate[0] = width / 2.0 - translate[1] = height / 2.0 - translate[2] = (maxz - minz) / 2.0 - translate[3] = 0.0 - viewport.translate = translate - ctx.set_viewport(viewport) - - # samplers - sampler = Sampler() - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE - sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.normalized_coords = 1 - ctx.set_sampler(0, sampler) - - # scissor - scissor = Scissor() - scissor.minx = 0 - scissor.miny = 0 - scissor.maxx = width - scissor.maxy = height - ctx.set_scissor(scissor) - - clip = Clip() - clip.nr = 0 - ctx.set_clip(clip) - - # framebuffer - cbuf = dev.resource_create( - PIPE_FORMAT_B8G8R8X8_UNORM, - width, height, - bind=PIPE_BIND_RENDER_TARGET, - ).get_surface() - zbuf = dev.resource_create( - PIPE_FORMAT_Z32_UNORM, - width, height, - bind=PIPE_BIND_DEPTH_STENCIL, - ).get_surface() - fb = Framebuffer() - fb.width = width - fb.height = height - fb.nr_cbufs = 1 - fb.set_cbuf(0, cbuf) - fb.set_zsbuf(zbuf) - ctx.set_framebuffer(fb) - rgba = FloatArray(4); - rgba[0] = 0.0 - rgba[1] = 0.0 - rgba[2] = 0.0 - rgba[3] = 0.0 - ctx.clear(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0xff) - - # vertex shader - vs = Shader(''' - VERT - DCL IN[0], POSITION, CONSTANT - DCL IN[1], COLOR, CONSTANT - DCL OUT[0], POSITION, CONSTANT - DCL OUT[1], COLOR, CONSTANT - 0:MOV OUT[0], IN[0] - 1:MOV OUT[1], IN[1] - 2:END - ''') - ctx.set_vertex_shader(vs) - - gs = Shader(''' - GEOM - PROPERTY GS_INPUT_PRIMITIVE TRIANGLES - PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP - DCL IN[][0], POSITION, CONSTANT - DCL IN[][1], COLOR, CONSTANT - DCL OUT[0], POSITION, CONSTANT - DCL OUT[1], COLOR, CONSTANT - 0:MOV OUT[0], IN[0][0] - 1:MOV OUT[1], IN[0][1] - 2:EMIT - 3:MOV OUT[0], IN[1][0] - 4:MOV OUT[1], IN[1][1] - 5:EMIT - 6:MOV OUT[0], IN[2][0] - 7:MOV OUT[1], IN[2][1] - 8:EMIT - 9:ENDPRIM - 10:END - ''') - ctx.set_geometry_shader(gs) - - # fragment shader - fs = Shader(''' - FRAG - DCL IN[0], COLOR, LINEAR - DCL OUT[0], COLOR, CONSTANT - 0:MOV OUT[0], IN[0] - 1:END - ''') - ctx.set_fragment_shader(fs) - - nverts = 3 - nattrs = 2 - verts = FloatArray(nverts * nattrs * 4) - - verts[ 0] = 0.0 # x1 - verts[ 1] = 0.8 # y1 - verts[ 2] = 0.2 # z1 - verts[ 3] = 1.0 # w1 - verts[ 4] = 1.0 # r1 - verts[ 5] = 0.0 # g1 - verts[ 6] = 0.0 # b1 - verts[ 7] = 1.0 # a1 - verts[ 8] = -0.8 # x2 - verts[ 9] = -0.8 # y2 - verts[10] = 0.5 # z2 - verts[11] = 1.0 # w2 - verts[12] = 0.0 # r2 - verts[13] = 1.0 # g2 - verts[14] = 0.0 # b2 - verts[15] = 1.0 # a2 - verts[16] = 0.8 # x3 - verts[17] = -0.8 # y3 - verts[18] = 0.8 # z3 - verts[19] = 1.0 # w3 - verts[20] = 0.0 # r3 - verts[21] = 0.0 # g3 - verts[22] = 1.0 # b3 - verts[23] = 1.0 # a3 - - ctx.draw_vertices(PIPE_PRIM_TRIANGLES, - nverts, - nattrs, - verts) - - ctx.flush() - - show_image(cbuf) - #show_image(zbuf) - #save_image('cbuf.png', cbuf) - #save_image('zbuf.png', zbuf) - - - -def main(): - dev = Device() - test(dev) - - -if __name__ == '__main__': - main() diff --git a/src/gallium/tests/python/samples/tri.py b/src/gallium/tests/python/samples/tri.py deleted file mode 100644 index 6d17c88c057..00000000000 --- a/src/gallium/tests/python/samples/tri.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -from gallium import * - - -def make_image(ctx, surface): - data = ctx.surface_read_rgba8(surface, 0, 0, surface.width, surface.height) - - import Image - outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) - return outimage - -def save_image(ctx, surface, filename): - outimage = make_image(ctx, surface) - outimage.save(filename, "PNG") - -def show_image(ctx, surface): - outimage = make_image(ctx, surface) - - import Tkinter as tk - from PIL import Image, ImageTk - root = tk.Tk() - - root.title('background image') - - image1 = ImageTk.PhotoImage(outimage) - w = image1.width() - h = image1.height() - x = 100 - y = 100 - root.geometry("%dx%d+%d+%d" % (w, h, x, y)) - panel1 = tk.Label(root, image=image1) - panel1.pack(side='top', fill='both', expand='yes') - panel1.image = image1 - root.mainloop() - - -def test(dev): - ctx = dev.context_create() - - width = 255 - height = 255 - minz = 0.0 - maxz = 1.0 - - # disabled blending/masking - blend = Blend() - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].colormask = PIPE_MASK_RGBA - ctx.set_blend(blend) - - # depth/stencil/alpha - depth_stencil_alpha = DepthStencilAlpha() - depth_stencil_alpha.depth.enabled = 1 - depth_stencil_alpha.depth.writemask = 1 - depth_stencil_alpha.depth.func = PIPE_FUNC_LESS - ctx.set_depth_stencil_alpha(depth_stencil_alpha) - - # rasterizer - rasterizer = Rasterizer() - rasterizer.front_ccw = False - rasterizer.cull_face = PIPE_FACE_NONE - rasterizer.scissor = 1 - ctx.set_rasterizer(rasterizer) - - # viewport - viewport = Viewport() - scale = FloatArray(4) - scale[0] = width / 2.0 - scale[1] = -height / 2.0 - scale[2] = (maxz - minz) / 2.0 - scale[3] = 1.0 - viewport.scale = scale - translate = FloatArray(4) - translate[0] = width / 2.0 - translate[1] = height / 2.0 - translate[2] = (maxz - minz) / 2.0 - translate[3] = 0.0 - viewport.translate = translate - ctx.set_viewport(viewport) - - # samplers - sampler = Sampler() - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE - sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.normalized_coords = 1 - ctx.set_fragment_sampler(0, sampler) - - # scissor - scissor = Scissor() - scissor.minx = 0 - scissor.miny = 0 - scissor.maxx = width - scissor.maxy = height - ctx.set_scissor(scissor) - - # clip - clip = Clip() - clip.nr = 0 - ctx.set_clip(clip) - - # framebuffer - cbuf = dev.resource_create( - PIPE_FORMAT_B8G8R8X8_UNORM, - width, height, - bind=PIPE_BIND_RENDER_TARGET, - ).get_surface() - zbuf = dev.resource_create( - PIPE_FORMAT_Z32_UNORM, - width, height, - bind=PIPE_BIND_DEPTH_STENCIL, - ).get_surface() - fb = Framebuffer() - fb.width = width - fb.height = height - fb.nr_cbufs = 1 - fb.set_cbuf(0, cbuf) - fb.set_zsbuf(zbuf) - ctx.set_framebuffer(fb) - rgba = FloatArray(4); - rgba[0] = 0.0 - rgba[1] = 0.0 - rgba[2] = 0.0 - rgba[3] = 0.0 - ctx.clear(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0xff) - - # vertex shader - vs = Shader(''' - VERT - DCL IN[0] - DCL IN[1] - DCL OUT[0], POSITION, CONSTANT - DCL OUT[1], COLOR, CONSTANT - 0:MOV OUT[0], IN[0] - 1:MOV OUT[1], IN[1] - 2:END - ''') - ctx.set_vertex_shader(vs) - - # fragment shader - fs = Shader(''' - FRAG - DCL IN[0], COLOR, LINEAR - DCL OUT[0], COLOR, CONSTANT - 0:MOV OUT[0], IN[0] - 1:END - ''') - ctx.set_fragment_shader(fs) - - nverts = 3 - nattrs = 2 - verts = FloatArray(nverts * nattrs * 4) - - verts[ 0] = 0.0 # x1 - verts[ 1] = 0.8 # y1 - verts[ 2] = 0.2 # z1 - verts[ 3] = 1.0 # w1 - verts[ 4] = 1.0 # r1 - verts[ 5] = 0.0 # g1 - verts[ 6] = 0.0 # b1 - verts[ 7] = 1.0 # a1 - verts[ 8] = -0.8 # x2 - verts[ 9] = -0.8 # y2 - verts[10] = 0.5 # z2 - verts[11] = 1.0 # w2 - verts[12] = 0.0 # r2 - verts[13] = 1.0 # g2 - verts[14] = 0.0 # b2 - verts[15] = 1.0 # a2 - verts[16] = 0.8 # x3 - verts[17] = -0.8 # y3 - verts[18] = 0.8 # z3 - verts[19] = 1.0 # w3 - verts[20] = 0.0 # r3 - verts[21] = 0.0 # g3 - verts[22] = 1.0 # b3 - verts[23] = 1.0 # a3 - - ctx.draw_vertices(PIPE_PRIM_TRIANGLES, - nverts, - nattrs, - verts) - - ctx.flush() - - show_image(ctx, cbuf) - show_image(ctx, zbuf) - save_image(ctx, cbuf, 'cbuf.png') - save_image(ctx, zbuf, 'zbuf.png') - - - -def main(): - dev = Device() - test(dev) - - -if __name__ == '__main__': - main() diff --git a/src/gallium/tests/python/tests/.gitignore b/src/gallium/tests/python/tests/.gitignore deleted file mode 100644 index 0dbbaeea16b..00000000000 --- a/src/gallium/tests/python/tests/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.txt -*.tsv -*.dot diff --git a/src/gallium/tests/python/tests/base.py b/src/gallium/tests/python/tests/base.py deleted file mode 100755 index d8cf84db363..00000000000 --- a/src/gallium/tests/python/tests/base.py +++ /dev/null @@ -1,399 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2009 VMware, Inc. -# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -"""Base classes for tests. - -Loosely inspired on Python's unittest module. -""" - - -import os.path -import sys - -from gallium import * - - -# Enumerate all pixel formats -formats = {} -for name, value in globals().items(): - if name.startswith("PIPE_FORMAT_") and isinstance(value, int) and name not in ("PIPE_FORMAT_NONE", "PIPE_FORMAT_COUNT"): - formats[value] = name - -def make_image(width, height, rgba): - import Image - outimage = Image.new( - mode='RGB', - size=(width, height), - color=(0,0,0)) - outpixels = outimage.load() - for y in range(0, height): - for x in range(0, width): - offset = (y*width + x)*4 - r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)] - outpixels[x, y] = r, g, b - return outimage - -def save_image(width, height, rgba, filename): - outimage = make_image(width, height, rgba) - outimage.save(filename, "PNG") - -def show_image(width, height, **rgbas): - import Tkinter as tk - from PIL import Image, ImageTk - - root = tk.Tk() - - x = 64 - y = 64 - - labels = rgbas.keys() - labels.sort() - for i in range(len(labels)): - label = labels[i] - outimage = make_image(width, height, rgbas[label]) - - if i: - window = tk.Toplevel(root) - else: - window = root - window.title(label) - image1 = ImageTk.PhotoImage(outimage) - w = image1.width() - h = image1.height() - window.geometry("%dx%d+%d+%d" % (w, h, x, y)) - panel1 = tk.Label(window, image=image1) - panel1.pack(side='top', fill='both', expand='yes') - panel1.image = image1 - x += w + 2 - - root.mainloop() - - -class TestFailure(Exception): - - pass - -class TestSkip(Exception): - - pass - - -class Test: - - def __init__(self): - pass - - def _run(self, result): - raise NotImplementedError - - def run(self): - result = TestResult() - self._run(result) - result.report() - - def assert_rgba(self, ctx, surface, x, y, w, h, expected_rgba, pixel_tol=4.0/256, surface_tol=0.85): - total = h*w - different = ctx.surface_compare_rgba(surface, x, y, w, h, expected_rgba, tol=pixel_tol) - if different: - sys.stderr.write("%u out of %u pixels differ\n" % (different, total)) - - if float(total - different)/float(total) < surface_tol: - if 0: - rgba = FloatArray(h*w*4) - ctx.surface_read_rgba(surface, x, y, w, h, rgba) - show_image(w, h, Result=rgba, Expected=expected_rgba) - save_image(w, h, rgba, "result.png") - save_image(w, h, expected_rgba, "expected.png") - #sys.exit(0) - - raise TestFailure - - -class TestCase(Test): - - tags = () - - def __init__(self, dev, **kargs): - Test.__init__(self) - self.dev = dev - self.__dict__.update(kargs) - - def description(self): - descriptions = [] - for tag in self.tags: - value = self.get(tag) - if value is not None and value != '': - descriptions.append(tag + '=' + str(value)) - return ' '.join(descriptions) - - def get(self, tag): - try: - method = getattr(self, '_get_' + tag) - except AttributeError: - return getattr(self, tag, None) - else: - return method() - - def _get_target(self): - return { - PIPE_TEXTURE_1D: "1d", - PIPE_TEXTURE_2D: "2d", - PIPE_TEXTURE_3D: "3d", - PIPE_TEXTURE_CUBE: "cube", - }[self.target] - - def _get_format(self): - name = formats[self.format] - if name.startswith('PIPE_FORMAT_'): - name = name[12:] - name = name.lower() - return name - - def _get_face(self): - if self.target == PIPE_TEXTURE_CUBE: - return { - PIPE_TEX_FACE_POS_X: "+x", - PIPE_TEX_FACE_NEG_X: "-x", - PIPE_TEX_FACE_POS_Y: "+y", - PIPE_TEX_FACE_NEG_Y: "-y", - PIPE_TEX_FACE_POS_Z: "+z", - PIPE_TEX_FACE_NEG_Z: "-z", - }[self.face] - else: - return '' - - def test(self): - raise NotImplementedError - - def _run(self, result): - result.test_start(self) - try: - self.test() - except KeyboardInterrupt: - raise - except TestSkip: - result.test_skipped(self) - except TestFailure: - result.test_failed(self) - else: - result.test_passed(self) - - -class TestSuite(Test): - - def __init__(self, tests = None): - Test.__init__(self) - if tests is None: - self.tests = [] - else: - self.tests = tests - - def add_test(self, test): - self.tests.append(test) - - def _run(self, result): - for test in self.tests: - test._run(result) - - -class TestResult: - - def __init__(self): - self.tests = 0 - self.passed = 0 - self.skipped = 0 - self.failed = 0 - - self.names = ['result'] - self.types = ['pass skip fail'] - self.rows = [] - - def test_start(self, test): - sys.stdout.write("Running %s...\n" % test.description()) - sys.stdout.flush() - self.tests += 1 - - def test_passed(self, test): - sys.stdout.write("PASS\n") - sys.stdout.flush() - self.passed += 1 - self.log_result(test, 'pass') - - def test_skipped(self, test): - sys.stdout.write("SKIP\n") - sys.stdout.flush() - self.skipped += 1 - self.log_result(test, 'skip') - - def test_failed(self, test): - sys.stdout.write("FAIL\n") - sys.stdout.flush() - self.failed += 1 - self.log_result(test, 'fail') - - def log_result(self, test, result): - row = ['']*len(self.names) - - # add result - assert self.names[0] == 'result' - assert result in ('pass', 'skip', 'fail') - row[0] = result - - # add tags - for tag in test.tags: - value = test.get(tag) - - # infer type - if value is None: - continue - elif isinstance(value, (int, float)): - value = str(value) - type = 'c' # continous - elif isinstance(value, basestring): - type = 'd' # discrete - else: - assert False - value = str(value) - type = 'd' # discrete - - # insert value - try: - col = self.names.index(tag, 1) - except ValueError: - self.names.append(tag) - self.types.append(type) - row.append(value) - else: - row[col] = value - assert self.types[col] == type - - self.rows.append(row) - - def report(self): - sys.stdout.write("%u tests, %u passed, %u skipped, %u failed\n\n" % (self.tests, self.passed, self.skipped, self.failed)) - sys.stdout.flush() - - name, ext = os.path.splitext(os.path.basename(sys.argv[0])) - - tree = self.report_tree(name) - self.report_junit(name, stdout=tree) - - def report_tree(self, name): - filename = name + '.tsv' - stream = file(filename, 'wt') - - # header - stream.write('\t'.join(self.names) + '\n') - stream.write('\t'.join(self.types) + '\n') - stream.write('class\n') - - # rows - for row in self.rows: - if row[0] == 'skip': - continue - row += ['']*(len(self.names) - len(row)) - stream.write('\t'.join(row) + '\n') - - stream.close() - - # See http://www.ailab.si/orange/doc/ofb/c_otherclass.htm - try: - import orange - import orngTree - except ImportError: - sys.stderr.write('Install Orange from http://www.ailab.si/orange/ for a classification tree.\n') - return None - - data = orange.ExampleTable(filename) - - tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2) - - orngTree.printTxt(tree, maxDepth=4) - - text_tree = orngTree.dumpTree(tree) - - file(name + '.txt', 'wt').write(text_tree) - - orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box') - - return text_tree - - def report_junit(self, name, stdout=None, stderr=None): - """Write test results in ANT's junit XML format, to use with Hudson CI. - - See also: - - http://fisheye.hudson-ci.org/browse/Hudson/trunk/hudson/main/core/src/test/resources/hudson/tasks/junit - - http://www.junit.org/node/399 - - http://wiki.apache.org/ant/Proposals/EnhancedTestReports - """ - - stream = file(name + '.xml', 'wt') - - stream.write('<?xml version="1.0" encoding="UTF-8" ?>\n') - stream.write('<testsuite name="%s">\n' % self.escape_xml(name)) - stream.write(' <properties>\n') - stream.write(' </properties>\n') - - names = self.names[1:] - - for row in self.rows: - - test_name = ' '.join(['%s=%s' % pair for pair in zip(self.names[1:], row[1:])]) - - stream.write(' <testcase name="%s">\n' % (self.escape_xml(test_name))) - - result = row[0] - if result == 'pass': - pass - elif result == 'skip': - stream.write(' <skipped/>\n') - else: - stream.write(' <failure/>\n') - - stream.write(' </testcase>\n') - - if stdout: - stream.write(' <system-out>%s</system-out>\n' % self.escape_xml(stdout)) - if stderr: - stream.write(' <system-err>%s</system-err>\n' % self.escape_xml(stderr)) - - stream.write('</testsuite>\n') - - stream.close() - - def escape_xml(self, s): - '''Escape a XML string.''' - s = s.replace('&', '&') - s = s.replace('<', '<') - s = s.replace('>', '>') - s = s.replace('"', '"') - s = s.replace("'", ''') - return s - diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/.gitignore b/src/gallium/tests/python/tests/regress/fragment-shader/.gitignore deleted file mode 100644 index e33609d251c..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.png diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-abs.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-abs.sh deleted file mode 100644 index 103d7497f48..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-abs.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { -0.5, -0.4, -0.6, 0.0 } - -ADD TEMP[0], IN[0], IMM[0] -ABS OUT[0], TEMP[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-add.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-add.sh deleted file mode 100644 index bcb94205963..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-add.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -ADD OUT[0], IN[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-1d.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-1d.sh deleted file mode 100644 index 85fb9ea4e7f..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-1d.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR -DCL CONST[1] -DCL CONST[3] -DCL TEMP[0..1] - -ADD TEMP[0], IN[0], CONST[1] -RCP TEMP[1], CONST[3].xxxx -MUL OUT[0], TEMP[0], TEMP[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp3.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp3.sh deleted file mode 100644 index b5281975d4a..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp3.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DP3 OUT[0], IN[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp4.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp4.sh deleted file mode 100644 index d59df76e70b..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dp4.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DP4 OUT[0], IN[0].xyzx, IN[0].xyzx - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dst.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-dst.sh deleted file mode 100644 index fbb20fa9f62..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-dst.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DST OUT[0], IN[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-ex2.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-ex2.sh deleted file mode 100644 index b511288f4b6..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-ex2.sh +++ /dev/null @@ -1,11 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -EX2 TEMP[0], IN[0].xxxx -MUL OUT[0], TEMP[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-flr.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-flr.sh deleted file mode 100644 index 99a2f96103a..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-flr.sh +++ /dev/null @@ -1,15 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 2.5, 4.0, 2.0, 1.0 } -IMM FLT32 { 0.4, 0.25, 0.5, 1.0 } - -MUL TEMP[0], IN[0], IMM[0] -FLR TEMP[0], TEMP[0] -MUL OUT[0], TEMP[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-frc.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-frc.sh deleted file mode 100644 index a54c2623b0a..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-frc.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 2.7, 3.1, 4.5, 1.0 } - -MUL TEMP[0], IN[0], IMM[0] -FRC OUT[0], TEMP[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lg2.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-lg2.sh deleted file mode 100644 index 5f5b4be1092..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lg2.sh +++ /dev/null @@ -1,15 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 1.0, 0.0, 0.0, 0.0 } -IMM FLT32 { 0.5, 0.0, 0.0, 0.0 } - -ADD TEMP[0], IN[0], IMM[0] -LG2 TEMP[0].x, TEMP[0].xxxx -ADD OUT[0], TEMP[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lit.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-lit.sh deleted file mode 100644 index 6323c4712dc..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lit.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -LIT OUT[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lrp.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-lrp.sh deleted file mode 100644 index 740809d22e0..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-lrp.sh +++ /dev/null @@ -1,11 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -ABS TEMP[0], IN[0] -LRP OUT[0], TEMP[0], IN[0].xxxx, IN[0].yyyy - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad.sh deleted file mode 100644 index 413b9dc3916..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad.sh +++ /dev/null @@ -1,11 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -IMM FLT32 { 0.5, 0.4, 0.6, 1.0 } -IMM FLT32 { 0.5, 0.4, 0.6, 0.0 } - -MAD OUT[0], IN[0], IMM[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-max.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-max.sh deleted file mode 100644 index b69f2132612..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-max.sh +++ /dev/null @@ -1,10 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -IMM FLT32 { 0.4, 0.4, 0.4, 0.0 } - -MAX OUT[0], IN[0], IMM[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-min.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-min.sh deleted file mode 100644 index df284f49e71..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-min.sh +++ /dev/null @@ -1,10 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -IMM FLT32 { 0.6, 0.6, 0.6, 1.0 } - -MIN OUT[0], IN[0], IMM[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mov.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-mov.sh deleted file mode 100644 index 64af72f381b..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mov.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -MOV OUT[0], IN[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mul.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-mul.sh deleted file mode 100644 index bdd0b0026b9..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mul.sh +++ /dev/null @@ -1,10 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -IMM FLT32 { 0.5, 0.6, 0.7, 1.0 } - -MUL OUT[0], IN[0], IMM[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-rcp.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-rcp.sh deleted file mode 100644 index f4b611b26ab..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-rcp.sh +++ /dev/null @@ -1,15 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 1.0, 0.0, 0.0, 0.0 } -IMM FLT32 { 1.5, 0.0, 0.0, 0.0 } - -ADD TEMP[0], IN[0], IMM[0] -RCP TEMP[0].x, TEMP[0].xxxx -SUB OUT[0], TEMP[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-rsq.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-rsq.sh deleted file mode 100644 index d1e9b0b53be..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-rsq.sh +++ /dev/null @@ -1,15 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 1.0, 0.0, 0.0, 0.0 } -IMM FLT32 { 1.5, 0.0, 0.0, 0.0 } - -ADD TEMP[0], IN[0], IMM[0] -RSQ TEMP[0].x, TEMP[0].xxxx -SUB OUT[0], TEMP[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-sge.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-sge.sh deleted file mode 100644 index 1f33fac4727..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-sge.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 0.6, 0.6, 0.6, 0.0 } - -SGE TEMP[0], IN[0], IMM[0] -MUL OUT[0], IN[0], TEMP[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-slt.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-slt.sh deleted file mode 100644 index d58b7886a12..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-slt.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { 0.6, 0.6, 0.6, 0.0 } - -SLT TEMP[0], IN[0], IMM[0] -MUL OUT[0], IN[0], TEMP[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-abs.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-abs.sh deleted file mode 100644 index ecd19248c64..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-abs.sh +++ /dev/null @@ -1,13 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { -0.3, -0.5, -0.4, 0.0 } - -ADD TEMP[0], IN[0], IMM[0] -MOV OUT[0], |TEMP[0]| - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh deleted file mode 100644 index c2d99ddd15b..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh +++ /dev/null @@ -1,15 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -IMM FLT32 { -0.2, -0.3, -0.4, 0.0 } -IMM FLT32 { -1.0, -1.0, -1.0, -1.0 } - -ADD TEMP[0], IN[0], IMM[0] -MOV TEMP[0], -|TEMP[0]| -MUL OUT[0], TEMP[0], IMM[1] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-neg.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-neg.sh deleted file mode 100644 index a08ab6d2dcb..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-neg.sh +++ /dev/null @@ -1,11 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -DCL TEMP[0] - -SUB TEMP[0], IN[0], IN[0].yzxw -MOV OUT[0], -TEMP[0] - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-swz.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-swz.sh deleted file mode 100644 index 6110647d979..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-srcmod-swz.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -MOV OUT[0], IN[0].yxzw - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-sub.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-sub.sh deleted file mode 100644 index 673fca139aa..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-sub.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -SUB OUT[0], IN[0], IN[0].yzxw - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-xpd.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-xpd.sh deleted file mode 100644 index 6ec8b1184cc..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-xpd.sh +++ /dev/null @@ -1,8 +0,0 @@ -FRAG - -DCL IN[0], COLOR, LINEAR -DCL OUT[0], COLOR - -XPD OUT[0], IN[0], IN[0].yzxw - -END diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/fragment-shader.py b/src/gallium/tests/python/tests/regress/fragment-shader/fragment-shader.py deleted file mode 100644 index ef65a9c5a1b..00000000000 --- a/src/gallium/tests/python/tests/regress/fragment-shader/fragment-shader.py +++ /dev/null @@ -1,257 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2009 VMware, Inc. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - -import struct - -from gallium import * - -def make_image(surface): - data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) - - import Image - outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) - return outimage - -def save_image(filename, surface): - outimage = make_image(surface) - outimage.save(filename, "PNG") - -def test(dev, name): - ctx = dev.context_create() - - width = 320 - height = 320 - minz = 0.0 - maxz = 1.0 - - # disabled blending/masking - blend = Blend() - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].colormask = PIPE_MASK_RGBA - ctx.set_blend(blend) - - # depth/stencil/alpha - depth_stencil_alpha = DepthStencilAlpha() - depth_stencil_alpha.depth.enabled = 0 - depth_stencil_alpha.depth.writemask = 1 - depth_stencil_alpha.depth.func = PIPE_FUNC_LESS - ctx.set_depth_stencil_alpha(depth_stencil_alpha) - - # rasterizer - rasterizer = Rasterizer() - rasterizer.front_winding = PIPE_WINDING_CW - rasterizer.cull_mode = PIPE_WINDING_NONE - rasterizer.scissor = 1 - ctx.set_rasterizer(rasterizer) - - # viewport - viewport = Viewport() - scale = FloatArray(4) - scale[0] = width / 2.0 - scale[1] = -height / 2.0 - scale[2] = (maxz - minz) / 2.0 - scale[3] = 1.0 - viewport.scale = scale - translate = FloatArray(4) - translate[0] = width / 2.0 - translate[1] = height / 2.0 - translate[2] = (maxz - minz) / 2.0 - translate[3] = 0.0 - viewport.translate = translate - ctx.set_viewport(viewport) - - # samplers - sampler = Sampler() - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE - sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.normalized_coords = 1 - ctx.set_fragment_sampler(0, sampler) - - # scissor - scissor = Scissor() - scissor.minx = 0 - scissor.miny = 0 - scissor.maxx = width - scissor.maxy = height - ctx.set_scissor(scissor) - - clip = Clip() - clip.nr = 0 - ctx.set_clip(clip) - - # framebuffer - cbuf = dev.resource_create( - PIPE_FORMAT_B8G8R8X8_UNORM, - width, height, - bind=PIPE_BIND_RENDER_TARGET, - ).get_surface() - fb = Framebuffer() - fb.width = width - fb.height = height - fb.nr_cbufs = 1 - fb.set_cbuf(0, cbuf) - ctx.set_framebuffer(fb) - rgba = FloatArray(4); - rgba[0] = 0.5 - rgba[1] = 0.5 - rgba[2] = 0.5 - rgba[3] = 0.5 - ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) - - # vertex shader - vs = Shader(''' - VERT - DCL IN[0], POSITION - DCL IN[1], COLOR - DCL OUT[0], POSITION - DCL OUT[1], COLOR - MOV OUT[0], IN[0] - MOV OUT[1], IN[1] - END - ''') - ctx.set_vertex_shader(vs) - - # fragment shader - fs = Shader(file('frag-' + name + '.sh', 'rt').read()) - ctx.set_fragment_shader(fs) - - constbuf0 = dev.buffer_create(64, - (PIPE_BUFFER_USAGE_CONSTANT | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE), - 4 * 4 * 4) - - cbdata = '' - cbdata += struct.pack('4f', 0.4, 0.0, 0.0, 1.0) - cbdata += struct.pack('4f', 1.0, 1.0, 1.0, 1.0) - cbdata += struct.pack('4f', 2.0, 2.0, 2.0, 2.0) - cbdata += struct.pack('4f', 4.0, 8.0, 16.0, 32.0) - - constbuf0.write(cbdata, 0) - - ctx.set_constant_buffer(PIPE_SHADER_FRAGMENT, - 0, - constbuf0) - - constbuf1 = dev.buffer_create(64, - (PIPE_BUFFER_USAGE_CONSTANT | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE), - 4 * 4 * 4) - - cbdata = '' - cbdata += struct.pack('4f', 0.1, 0.1, 0.1, 0.1) - cbdata += struct.pack('4f', 0.25, 0.25, 0.25, 0.25) - cbdata += struct.pack('4f', 0.5, 0.5, 0.5, 0.5) - cbdata += struct.pack('4f', 0.75, 0.75, 0.75, 0.75) - - constbuf1.write(cbdata, 0) - - ctx.set_constant_buffer(PIPE_SHADER_FRAGMENT, - 1, - constbuf1) - - xy = [ - -0.8, -0.8, - 0.8, -0.8, - 0.0, 0.8, - ] - color = [ - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - ] - - nverts = 3 - nattrs = 2 - verts = FloatArray(nverts * nattrs * 4) - - for i in range(0, nverts): - verts[i * nattrs * 4 + 0] = xy[i * 2 + 0] # x - verts[i * nattrs * 4 + 1] = xy[i * 2 + 1] # y - verts[i * nattrs * 4 + 2] = 0.5 # z - verts[i * nattrs * 4 + 3] = 1.0 # w - verts[i * nattrs * 4 + 4] = color[i * 3 + 0] # r - verts[i * nattrs * 4 + 5] = color[i * 3 + 1] # g - verts[i * nattrs * 4 + 6] = color[i * 3 + 2] # b - verts[i * nattrs * 4 + 7] = 1.0 # a - - ctx.draw_vertices(PIPE_PRIM_TRIANGLES, - nverts, - nattrs, - verts) - - ctx.flush() - - save_image('frag-' + name + '.png', cbuf) - -def main(): - tests = [ - 'abs', - 'add', - 'cb-1d', - 'cb-2d', - 'dp3', - 'dp4', - 'dst', - 'ex2', - 'flr', - 'frc', - 'lg2', - 'lit', - 'lrp', - 'mad', - 'max', - 'min', - 'mov', - 'mul', - 'rcp', - 'rsq', - 'sge', - 'slt', - 'srcmod-abs', - 'srcmod-absneg', - 'srcmod-neg', - 'srcmod-swz', - 'sub', - 'xpd', - ] - - dev = Device() - for t in tests: - test(dev, t) - -if __name__ == '__main__': - main() diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/.gitignore b/src/gallium/tests/python/tests/regress/vertex-shader/.gitignore deleted file mode 100644 index e33609d251c..00000000000 --- a/src/gallium/tests/python/tests/regress/vertex-shader/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.png diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vertex-shader.py b/src/gallium/tests/python/tests/regress/vertex-shader/vertex-shader.py deleted file mode 100644 index 05e40dbd5f1..00000000000 --- a/src/gallium/tests/python/tests/regress/vertex-shader/vertex-shader.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2009 VMware, Inc. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -import struct - -from gallium import * - -def make_image(surface): - data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) - - import Image - outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) - return outimage - -def save_image(filename, surface): - outimage = make_image(surface) - outimage.save(filename, "PNG") - -def test(dev, name): - ctx = dev.context_create() - - width = 320 - height = 320 - minz = 0.0 - maxz = 1.0 - - # disabled blending/masking - blend = Blend() - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].colormask = PIPE_MASK_RGBA - ctx.set_blend(blend) - - # depth/stencil/alpha - depth_stencil_alpha = DepthStencilAlpha() - depth_stencil_alpha.depth.enabled = 0 - depth_stencil_alpha.depth.writemask = 1 - depth_stencil_alpha.depth.func = PIPE_FUNC_LESS - ctx.set_depth_stencil_alpha(depth_stencil_alpha) - - # rasterizer - rasterizer = Rasterizer() - rasterizer.front_winding = PIPE_WINDING_CW - rasterizer.cull_mode = PIPE_WINDING_NONE - rasterizer.scissor = 1 - ctx.set_rasterizer(rasterizer) - - # viewport - viewport = Viewport() - scale = FloatArray(4) - scale[0] = width / 2.0 - scale[1] = -height / 2.0 - scale[2] = (maxz - minz) / 2.0 - scale[3] = 1.0 - viewport.scale = scale - translate = FloatArray(4) - translate[0] = width / 2.0 - translate[1] = height / 2.0 - translate[2] = (maxz - minz) / 2.0 - translate[3] = 0.0 - viewport.translate = translate - ctx.set_viewport(viewport) - - # samplers - sampler = Sampler() - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE - sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.normalized_coords = 1 - ctx.set_fragment_sampler(0, sampler) - - # scissor - scissor = Scissor() - scissor.minx = 0 - scissor.miny = 0 - scissor.maxx = width - scissor.maxy = height - ctx.set_scissor(scissor) - - clip = Clip() - clip.nr = 0 - ctx.set_clip(clip) - - # framebuffer - cbuf = dev.resource_create( - PIPE_FORMAT_B8G8R8X8_UNORM, - width, height, - bind=PIPE_BIND_RENDER_TARGET, - ).get_surface() - fb = Framebuffer() - fb.width = width - fb.height = height - fb.nr_cbufs = 1 - fb.set_cbuf(0, cbuf) - ctx.set_framebuffer(fb) - rgba = FloatArray(4); - rgba[0] = 0.5 - rgba[1] = 0.5 - rgba[2] = 0.5 - rgba[3] = 0.5 - ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) - - # vertex shader - vs = Shader(file('vert-' + name + '.sh', 'rt').read()) - ctx.set_vertex_shader(vs) - - # fragment shader - fs = Shader(''' - FRAG - DCL IN[0], COLOR, LINEAR - DCL OUT[0], COLOR, CONSTANT - 0:MOV OUT[0], IN[0] - 1:END - ''') - ctx.set_fragment_shader(fs) - - constbuf0 = dev.buffer_create(64, - (PIPE_BUFFER_USAGE_CONSTANT | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE), - 4 * 4 * 4) - - cbdata = '' - cbdata += struct.pack('4f', 0.4, 0.0, 0.0, 1.0) - cbdata += struct.pack('4f', 1.0, 1.0, 1.0, 1.0) - cbdata += struct.pack('4f', 2.0, 2.0, 2.0, 2.0) - cbdata += struct.pack('4f', 4.0, 8.0, 16.0, 32.0) - - constbuf0.write(cbdata, 0) - - ctx.set_constant_buffer(PIPE_SHADER_VERTEX, - 0, - constbuf0) - - constbuf1 = dev.buffer_create(64, - (PIPE_BUFFER_USAGE_CONSTANT | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE), - 4 * 4 * 4) - - cbdata = '' - cbdata += struct.pack('4f', 0.1, 0.1, 0.1, 0.1) - cbdata += struct.pack('4f', 0.25, 0.25, 0.25, 0.25) - cbdata += struct.pack('4f', 0.5, 0.5, 0.5, 0.5) - cbdata += struct.pack('4f', 0.75, 0.75, 0.75, 0.75) - - constbuf1.write(cbdata, 0) - - ctx.set_constant_buffer(PIPE_SHADER_VERTEX, - 1, - constbuf1) - - xy = [ - 0.0, 0.8, - -0.2, 0.4, - 0.2, 0.4, - -0.4, 0.0, - 0.0, 0.0, - 0.4, 0.0, - -0.6, -0.4, - -0.2, -0.4, - 0.2, -0.4, - 0.6, -0.4, - -0.8, -0.8, - -0.4, -0.8, - 0.0, -0.8, - 0.4, -0.8, - 0.8, -0.8, - ] - color = [ - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - ] - tri = [ - 1, 2, 0, - 3, 4, 1, - 4, 2, 1, - 4, 5, 2, - 6, 7, 3, - 7, 4, 3, - 7, 8, 4, - 8, 5, 4, - 8, 9, 5, - 10, 11, 6, - 11, 7, 6, - 11, 12, 7, - 12, 8, 7, - 12, 13, 8, - 13, 9, 8, - 13, 14, 9, - ] - - nverts = 16 * 3 - nattrs = 2 - verts = FloatArray(nverts * nattrs * 4) - - for i in range(0, nverts): - verts[i * nattrs * 4 + 0] = xy[tri[i] * 2 + 0] # x - verts[i * nattrs * 4 + 1] = xy[tri[i] * 2 + 1] # y - verts[i * nattrs * 4 + 2] = 0.5 # z - verts[i * nattrs * 4 + 3] = 1.0 # w - verts[i * nattrs * 4 + 4] = color[(i % 3) * 3 + 0] # r - verts[i * nattrs * 4 + 5] = color[(i % 3) * 3 + 1] # g - verts[i * nattrs * 4 + 6] = color[(i % 3) * 3 + 2] # b - verts[i * nattrs * 4 + 7] = 1.0 # a - - ctx.draw_vertices(PIPE_PRIM_TRIANGLES, - nverts, - nattrs, - verts) - - ctx.flush() - - save_image('vert-' + name + '.png', cbuf) - -def main(): - tests = [ - 'abs', - 'add', - 'arl', - 'arr', - 'cb-1d', - 'cb-2d', - 'dp3', - 'dp4', - 'dst', - 'ex2', - 'flr', - 'frc', - 'lg2', - 'lit', - 'lrp', - 'mad', - 'max', - 'min', - 'mov', - 'mul', - 'rcp', - 'rsq', - 'sge', - 'slt', - 'srcmod-abs', - 'srcmod-absneg', - 'srcmod-neg', - 'srcmod-swz', - 'sub', - 'xpd', - ] - - dev = Device() - for t in tests: - test(dev, t) - -if __name__ == '__main__': - main() diff --git a/src/gallium/tests/python/tests/texture_render.py b/src/gallium/tests/python/tests/texture_render.py deleted file mode 100755 index 23f3d2a57de..00000000000 --- a/src/gallium/tests/python/tests/texture_render.py +++ /dev/null @@ -1,320 +0,0 @@ -#!/usr/bin/env python -########################################################################## -# -# Copyright 2009 VMware, Inc. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sub license, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice (including the -# next paragraph) shall be included in all copies or substantial portions -# of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -########################################################################## - - -from gallium import * -from base import * - - -def lods(*dims): - size = max(dims) - lods = 0 - while size: - lods += 1 - size >>= 1 - return lods - - -class TextureTest(TestCase): - - tags = ( - 'target', - 'format', - 'width', - 'height', - 'depth', - 'last_level', - 'face', - 'level', - 'zslice', - ) - - def test(self): - dev = self.dev - - target = self.target - format = self.format - width = self.width - height = self.height - depth = self.depth - last_level = self.last_level - face = self.face - level = self.level - zslice = self.zslice - - # textures - dst_texture = dev.resource_create( - target = target, - format = format, - width = width, - height = height, - depth = depth, - last_level = last_level, - bind = PIPE_BIND_RENDER_TARGET, - ) - if dst_texture is None: - raise TestSkip - - dst_surface = dst_texture.get_surface(face = face, level = level, zslice = zslice) - - ref_texture = dev.resource_create( - target = target, - format = format, - width = dst_surface.width, - height = dst_surface.height, - depth = 1, - last_level = 0, - bind = PIPE_BIND_SAMPLER_VIEW, - ) - - ref_surface = ref_texture.get_surface() - - src_texture = dev.resource_create( - target = target, - format = PIPE_FORMAT_B8G8R8A8_UNORM, - width = dst_surface.width, - height = dst_surface.height, - depth = 1, - last_level = 0, - bind = PIPE_BIND_SAMPLER_VIEW, - ) - - src_surface = src_texture.get_surface() - - expected_rgba = FloatArray(height*width*4) - ref_surface.sample_rgba(expected_rgba) - - src_surface.put_tile_rgba(0, 0, src_surface.width, src_surface.height, expected_rgba) - - ctx = self.dev.context_create() - - # disabled blending/masking - blend = Blend() - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO - blend.rt[0].colormask = PIPE_MASK_RGBA - ctx.set_blend(blend) - - # no-op depth/stencil/alpha - depth_stencil_alpha = DepthStencilAlpha() - ctx.set_depth_stencil_alpha(depth_stencil_alpha) - - # rasterizer - rasterizer = Rasterizer() - rasterizer.front_winding = PIPE_WINDING_CW - rasterizer.cull_mode = PIPE_WINDING_NONE - rasterizer.bypass_vs_clip_and_viewport = 1 - ctx.set_rasterizer(rasterizer) - - # samplers - sampler = Sampler() - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST - sampler.normalized_coords = 1 - sampler.min_lod = 0 - sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1 - ctx.set_fragment_sampler(0, sampler) - ctx.set_fragment_sampler_texture(0, src_texture) - - # framebuffer - cbuf_tex = dev.resource_create( - PIPE_FORMAT_B8G8R8A8_UNORM, - width, - height, - bind = PIPE_BIND_RENDER_TARGET, - ) - - fb = Framebuffer() - fb.width = dst_surface.width - fb.height = dst_surface.height - fb.nr_cbufs = 1 - fb.set_cbuf(0, dst_surface) - ctx.set_framebuffer(fb) - rgba = FloatArray(4); - rgba[0] = 0.0 - rgba[1] = 0.0 - rgba[2] = 0.0 - rgba[3] = 0.0 - ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) - del fb - - # vertex shader - vs = Shader(''' - VERT - DCL IN[0], POSITION, CONSTANT - DCL IN[1], GENERIC, CONSTANT - DCL OUT[0], POSITION, CONSTANT - DCL OUT[1], GENERIC, CONSTANT - 0:MOV OUT[0], IN[0] - 1:MOV OUT[1], IN[1] - 2:END - ''') - #vs.dump() - ctx.set_vertex_shader(vs) - - # fragment shader - fs = Shader(''' - FRAG - DCL IN[0], GENERIC[0], LINEAR - DCL OUT[0], COLOR, CONSTANT - DCL SAMP[0], CONSTANT - 0:TEX OUT[0], IN[0], SAMP[0], 2D - 1:END - ''') - #fs.dump() - ctx.set_fragment_shader(fs) - - nverts = 4 - nattrs = 2 - verts = FloatArray(nverts * nattrs * 4) - - x = 0 - y = 0 - w = dst_surface.width - h = dst_surface.height - - pos = [ - [x, y], - [x+w, y], - [x+w, y+h], - [x, y+h], - ] - - tex = [ - [0.0, 0.0], - [1.0, 0.0], - [1.0, 1.0], - [0.0, 1.0], - ] - - for i in range(0, 4): - j = 8*i - verts[j + 0] = pos[i][0] # x - verts[j + 1] = pos[i][1] # y - verts[j + 2] = 0.0 # z - verts[j + 3] = 1.0 # w - verts[j + 4] = tex[i][0] # s - verts[j + 5] = tex[i][1] # r - verts[j + 6] = 0.0 - verts[j + 7] = 1.0 - - ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN, - nverts, - nattrs, - verts) - - ctx.flush() - - self.assert_rgba(dst_surface, x, y, w, h, expected_rgba, 4.0/256, 0.85) - - - -def main(): - dev = Device() - suite = TestSuite() - - targets = [ - PIPE_TEXTURE_2D, - PIPE_TEXTURE_CUBE, - #PIPE_TEXTURE_3D, - ] - - formats = [ - PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_FORMAT_B8G8R8X8_UNORM, - #PIPE_FORMAT_B8G8R8A8_SRGB, - PIPE_FORMAT_B5G6R5_UNORM, - PIPE_FORMAT_B5G5R5A1_UNORM, - PIPE_FORMAT_B4G4R4A4_UNORM, - #PIPE_FORMAT_Z32_UNORM, - #PIPE_FORMAT_S8_USCALED_Z24_UNORM, - #PIPE_FORMAT_X8Z24_UNORM, - #PIPE_FORMAT_Z16_UNORM, - #PIPE_FORMAT_S8_USCALED, - PIPE_FORMAT_A8_UNORM, - PIPE_FORMAT_L8_UNORM, - #PIPE_FORMAT_DXT1_RGB, - #PIPE_FORMAT_DXT1_RGBA, - #PIPE_FORMAT_DXT3_RGBA, - #PIPE_FORMAT_DXT5_RGBA, - ] - - sizes = [64, 32, 16, 8, 4, 2, 1] - #sizes = [1020, 508, 252, 62, 30, 14, 6, 3] - #sizes = [64] - #sizes = [63] - - faces = [ - PIPE_TEX_FACE_POS_X, - PIPE_TEX_FACE_NEG_X, - PIPE_TEX_FACE_POS_Y, - PIPE_TEX_FACE_NEG_Y, - PIPE_TEX_FACE_POS_Z, - PIPE_TEX_FACE_NEG_Z, - ] - - for target in targets: - for format in formats: - for size in sizes: - if target == PIPE_TEXTURE_3D: - depth = size - else: - depth = 1 - for face in faces: - if target != PIPE_TEXTURE_CUBE and face: - continue - levels = lods(size) - for last_level in range(levels): - for level in range(0, last_level + 1): - zslice = 0 - while zslice < depth >> level: - test = TextureTest( - dev = dev, - target = target, - format = format, - width = size, - height = size, - depth = depth, - last_level = last_level, - face = face, - level = level, - zslice = zslice, - ) - suite.add_test(test) - zslice = (zslice + 1)*2 - 1 - suite.run() - - -if __name__ == '__main__': - main() diff --git a/src/gallium/tests/python/tests/tree.py b/src/gallium/tests/python/tests/tree.py deleted file mode 100755 index 0c1bcda4cf2..00000000000 --- a/src/gallium/tests/python/tests/tree.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -# See also: -# http://www.ailab.si/orange/doc/ofb/c_otherclass.htm - -import os.path -import sys - -import orange -import orngTree - -for arg in sys.argv[1:]: - name, ext = os.path.splitext(arg) - - data = orange.ExampleTable(arg) - - tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2) - - orngTree.printTxt(tree) - - file(name+'.txt', 'wt').write(orngTree.dumpTree(tree) + '\n') - - orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box') diff --git a/src/gallium/tests/trivial/.gitignore b/src/gallium/tests/trivial/.gitignore deleted file mode 100644 index af6cdedbeba..00000000000 --- a/src/gallium/tests/trivial/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -tri -quad-tex -result.bmp diff --git a/src/gallium/tests/trivial/Makefile b/src/gallium/tests/trivial/Makefile deleted file mode 100644 index 2ed63419c7e..00000000000 --- a/src/gallium/tests/trivial/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# progs/gallium/simple/Makefile - -TOP = ../../../.. -include $(TOP)/configs/current - -INCLUDES = \ - -I. \ - -I$(TOP)/src/gallium/include \ - -I$(TOP)/src/gallium/auxiliary \ - -I$(TOP)/src/gallium/drivers \ - -I$(TOP)/src/gallium/winsys \ - $(PROG_INCLUDES) - -LINKS = \ - $(TOP)/src/gallium/drivers/rbug/librbug.a \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/drivers/galahad/libgalahad.a \ - $(TOP)/src/gallium/winsys/sw/null/libws_null.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(GALLIUM_AUXILIARIES) \ - $(PROG_LINKS) - -SOURCES = \ - tri.c \ - quad-tex.c - -OBJECTS = $(SOURCES:.c=.o) - -PROGS = $(OBJECTS:.o=) - -PROG_DEFINES = \ - -DGALLIUM_SOFTPIPE -DGALLIUM_RBUG -DGALLIUM_TRACE -DGALLIUM_GALAHAD - -##### TARGETS ##### - -default: $(PROGS) - -clean: - -rm -f $(PROGS) - -rm -f *.o - -rm -f result.bmp - -##### RULES ##### - -$(OBJECTS): %.o: %.c - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(PROG_DEFINES) $< -o $@ - -$(PROGS): %: %.o $(LINKS) - $(CC) $(LDFLAGS) $< $(LINKS) -lm -lpthread -ldl -o $@ diff --git a/src/gallium/tests/unit/Makefile b/src/gallium/tests/unit/Makefile deleted file mode 100644 index bb3039f3bc7..00000000000 --- a/src/gallium/tests/unit/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# progs/gallium/simple/Makefile - -TOP = ../../../.. -include $(TOP)/configs/current - -INCLUDES = \ - -I. \ - -I$(TOP)/src/gallium/include \ - -I$(TOP)/src/gallium/auxiliary \ - -I$(TOP)/src/gallium/drivers \ - -I$(TOP)/src/gallium/winsys \ - $(PROG_INCLUDES) - -LINKS = \ - $(TOP)/src/gallium/drivers/trace/libtrace.a \ - $(TOP)/src/gallium/winsys/sw/null/libws_null.a \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(GALLIUM_AUXILIARIES) \ - $(PROG_LINKS) - -SOURCES = \ - pipe_barrier_test.c \ - u_cache_test.c \ - u_half_test.c \ - u_format_test.c \ - u_format_compatible_test.c \ - translate_test.c - - -OBJECTS = $(SOURCES:.c=.o) - -PROGS = $(OBJECTS:.o=) - -##### TARGETS ##### - -default: $(PROGS) - -clean: - -rm -f $(PROGS) - -rm -f *.o - -rm -f result.bmp - -##### RULES ##### - -$(OBJECTS): %.o: %.c - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(PROG_DEFINES) $< -o $@ - -$(PROGS): %: %.o - $(CC) $(LDFLAGS) $< $(LINKS) -lm -lpthread -ldl -o $@ diff --git a/src/gallium/tests/unit/SConscript b/src/gallium/tests/unit/SConscript deleted file mode 100644 index 655e8a9b41c..00000000000 --- a/src/gallium/tests/unit/SConscript +++ /dev/null @@ -1,33 +0,0 @@ -Import('*') - -env = env.Clone() - -env.Prepend(LIBS = [gallium]) - -if env['platform'] in ('freebsd8', 'sunos5'): - env.Append(LIBS = ['m']) - -if env['platform'] == 'freebsd8': - env.Append(LIBS = ['pthread']) - -progs = [ - 'pipe_barrier_test', - 'u_cache_test', - 'u_format_test', - 'u_format_compatible_test', - 'u_half_test', - 'translate_test' -] - -for prog in progs: - prog = env.Program( - target = prog, - source = prog + '.c', - ) - - env.InstallProgram(prog) - - # http://www.scons.org/wiki/UnitTests - test_alias = env.Alias('unit', [prog], prog[0].abspath) - AlwaysBuild(test_alias) - diff --git a/src/gallium/tests/unit/u_cache_test.c b/src/gallium/tests/unit/u_cache_test.c deleted file mode 100644 index 0b62a765230..00000000000 --- a/src/gallium/tests/unit/u_cache_test.c +++ /dev/null @@ -1,121 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/* - * Test case for u_cache. - */ - - -#include <assert.h> -#include <stdio.h> - -#include "util/u_cache.h" -#include "util/u_hash.h" - - -typedef uint32_t cache_test_key; -typedef uint32_t cache_test_value; - - -static uint32_t -cache_test_hash(const void *key) -{ - return util_hash_crc32(key, sizeof(cache_test_key)); -} - - -static void -cache_test_destroy(void *key, void *value) -{ - free(key); - free(value); -} - - -static int -cache_test_compare(const void *key1, const void *key2) { - return !(key1 == key2); -} - - -int main() { - unsigned cache_size; - unsigned cache_count; - - for (cache_size = 2; cache_size < (1 << 15); cache_size *= 2) { - for (cache_count = (cache_size << 5); cache_count < (cache_size << 10); cache_count *= 2) { - struct util_cache * cache; - cache_test_key *key; - cache_test_value *value_in; - cache_test_value *value_out; - int i; - - printf("Testing cache size of %d with %d values.\n", cache_size, cache_count); - - cache = util_cache_create(cache_test_hash, - cache_test_compare, - cache_test_destroy, - cache_size); - - /* - * Retrieve a value from an empty cache. - */ - key = malloc(sizeof(cache_test_key)); - *key = 0xdeadbeef; - value_out = (cache_test_value *) util_cache_get(cache, key); - assert(value_out == NULL); - free(key); - - - /* - * Repeatedly insert into and retrieve values from the cache. - */ - for (i = 0; i < cache_count; i++) { - key = malloc(sizeof(cache_test_key)); - value_in = malloc(sizeof(cache_test_value)); - - *key = rand(); - *value_in = rand(); - util_cache_set(cache, key, value_in); - - value_out = util_cache_get(cache, key); - assert(value_out != NULL); - assert(value_in == value_out); - assert(*value_in == *value_out); - } - - /* - * In debug builds, this will trigger a self-check by the cache of - * the distribution of hits in its internal cache entries. - */ - util_cache_destroy(cache); - } - } - - return 0; -} diff --git a/src/gallium/tests/unit/u_format_test.c b/src/gallium/tests/unit/u_format_test.c deleted file mode 100644 index ba0dd17957e..00000000000 --- a/src/gallium/tests/unit/u_format_test.c +++ /dev/null @@ -1,716 +0,0 @@ -/************************************************************************** - * - * Copyright 2009-2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#include <stdlib.h> -#include <stdio.h> -#include <float.h> - -#include "util/u_half.h" -#include "util/u_format.h" -#include "util/u_format_tests.h" -#include "util/u_format_s3tc.h" - - -static boolean -compare_float(float x, float y) -{ - float error = y - x; - - if (error < 0.0f) - error = -error; - - if (error > FLT_EPSILON) { - return FALSE; - } - - return TRUE; -} - - -static void -print_packed(const struct util_format_description *format_desc, - const char *prefix, - const uint8_t *packed, - const char *suffix) -{ - unsigned i; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.bits/8; ++i) { - printf("%s%02x", sep, packed[i]); - sep = " "; - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_rgba_doubl(const struct util_format_description *format_desc, - const char *prefix, - const double unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s{%f, %f, %f, %f}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]); - sep = ", "; - } - sep = ",\n"; - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_rgba_float(const struct util_format_description *format_desc, - const char *prefix, - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s{%f, %f, %f, %f}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]); - sep = ", "; - } - sep = ",\n"; - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_rgba_8unorm(const struct util_format_description *format_desc, - const char *prefix, - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s{0x%02x, 0x%02x, 0x%02x, 0x%02x}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]); - sep = ", "; - } - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_z_float(const struct util_format_description *format_desc, - const char *prefix, - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s%f", sep, unpacked[i][j]); - sep = ", "; - } - sep = ",\n"; - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_z_32unorm(const struct util_format_description *format_desc, - const char *prefix, - uint32_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s0x%08x", sep, unpacked[i][j]); - sep = ", "; - } - } - printf("%s", suffix); - fflush(stdout); -} - - -static void -print_unpacked_s_8uscaled(const struct util_format_description *format_desc, - const char *prefix, - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH], - const char *suffix) -{ - unsigned i, j; - const char *sep = ""; - - printf("%s", prefix); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - printf("%s0x%02x", sep, unpacked[i][j]); - sep = ", "; - } - } - printf("%s", suffix); - fflush(stdout); -} - - -static boolean -test_format_fetch_rgba_float(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4] = { { { 0 } } }; - unsigned i, j, k; - boolean success; - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - format_desc->fetch_rgba_float(unpacked[i][j], test->packed, j, i); - for (k = 0; k < 4; ++k) { - if (!compare_float(test->unpacked[i][j][k], unpacked[i][j][k])) { - success = FALSE; - } - } - } - } - - if (!success) { - print_unpacked_rgba_float(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_rgba_doubl(format_desc, " ", test->unpacked, " expected\n"); - } - - return success; -} - - -static boolean -test_format_unpack_rgba_float(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4] = { { { 0 } } }; - unsigned i, j, k; - boolean success; - - format_desc->unpack_rgba_float(&unpacked[0][0][0], sizeof unpacked[0], - test->packed, 0, - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - for (k = 0; k < 4; ++k) { - if (!compare_float(test->unpacked[i][j][k], unpacked[i][j][k])) { - success = FALSE; - } - } - } - } - - if (!success) { - print_unpacked_rgba_float(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_rgba_doubl(format_desc, " ", test->unpacked, " expected\n"); - } - - return success; -} - - -static boolean -test_format_pack_rgba_float(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4]; - uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; - unsigned i, j, k; - boolean success; - - if (test->format == PIPE_FORMAT_DXT1_RGBA) { - /* - * Skip S3TC as packed representation is not canonical. - * - * TODO: Do a round trip conversion. - */ - return TRUE; - } - - memset(packed, 0, sizeof packed); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - for (k = 0; k < 4; ++k) { - unpacked[i][j][k] = (float) test->unpacked[i][j][k]; - } - } - } - - format_desc->pack_rgba_float(packed, 0, - &unpacked[0][0][0], sizeof unpacked[0], - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.bits/8; ++i) - if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) - success = FALSE; - - if (!success) { - print_packed(format_desc, "FAILED: ", packed, " obtained\n"); - print_packed(format_desc, " ", test->packed, " expected\n"); - } - - return success; -} - - -static boolean -convert_float_to_8unorm(uint8_t *dst, const double *src) -{ - unsigned i; - boolean accurate = TRUE; - - for (i = 0; i < UTIL_FORMAT_MAX_UNPACKED_HEIGHT*UTIL_FORMAT_MAX_UNPACKED_WIDTH*4; ++i) { - if (src[i] < 0.0) { - accurate = FALSE; - dst[i] = 0; - } - else if (src[i] > 1.0) { - accurate = FALSE; - dst[i] = 255; - } - else { - dst[i] = src[i] * 255.0; - } - } - - return accurate; -} - - -static boolean -test_format_unpack_rgba_8unorm(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4] = { { { 0 } } }; - uint8_t expected[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4] = { { { 0 } } }; - unsigned i, j, k; - boolean success; - - format_desc->unpack_rgba_8unorm(&unpacked[0][0][0], sizeof unpacked[0], - test->packed, 0, - format_desc->block.width, format_desc->block.height); - - convert_float_to_8unorm(&expected[0][0][0], &test->unpacked[0][0][0]); - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - for (k = 0; k < 4; ++k) { - if (expected[i][j][k] != unpacked[i][j][k]) { - success = FALSE; - } - } - } - } - - if (!success) { - print_unpacked_rgba_8unorm(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_rgba_8unorm(format_desc, " ", expected, " expected\n"); - } - - return success; -} - - -static boolean -test_format_pack_rgba_8unorm(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4]; - uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; - unsigned i; - boolean success; - - if (test->format == PIPE_FORMAT_DXT1_RGBA) { - /* - * Skip S3TC as packed representation is not canonical. - * - * TODO: Do a round trip conversion. - */ - return TRUE; - } - - if (!convert_float_to_8unorm(&unpacked[0][0][0], &test->unpacked[0][0][0])) { - /* - * Skip test cases which cannot be represented by four unorm bytes. - */ - return TRUE; - } - - memset(packed, 0, sizeof packed); - - format_desc->pack_rgba_8unorm(packed, 0, - &unpacked[0][0][0], sizeof unpacked[0], - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.bits/8; ++i) - if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) - success = FALSE; - - if (!success) { - print_packed(format_desc, "FAILED: ", packed, " obtained\n"); - print_packed(format_desc, " ", test->packed, " expected\n"); - } - - return success; -} - - -static boolean -test_format_unpack_z_float(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH] = { { 0 } }; - unsigned i, j; - boolean success; - - format_desc->unpack_z_float(&unpacked[0][0], sizeof unpacked[0], - test->packed, 0, - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - if (!compare_float(test->unpacked[i][j][0], unpacked[i][j])) { - success = FALSE; - } - } - } - - if (!success) { - print_unpacked_z_float(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_rgba_doubl(format_desc, " ", test->unpacked, " expected\n"); - } - - return success; -} - - -static boolean -test_format_pack_z_float(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH]; - uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; - unsigned i, j; - boolean success; - - memset(packed, 0, sizeof packed); - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - unpacked[i][j] = (float) test->unpacked[i][j][0]; - if (test->unpacked[i][j][1]) { - return TRUE; - } - } - } - - format_desc->pack_z_float(packed, 0, - &unpacked[0][0], sizeof unpacked[0], - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.bits/8; ++i) - if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) - success = FALSE; - - if (!success) { - print_packed(format_desc, "FAILED: ", packed, " obtained\n"); - print_packed(format_desc, " ", test->packed, " expected\n"); - } - - return success; -} - - -static boolean -test_format_unpack_z_32unorm(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint32_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH] = { { 0 } }; - uint32_t expected[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH] = { { 0 } }; - unsigned i, j; - boolean success; - - format_desc->unpack_z_32unorm(&unpacked[0][0], sizeof unpacked[0], - test->packed, 0, - format_desc->block.width, format_desc->block.height); - - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - expected[i][j] = test->unpacked[i][j][0] * 0xffffffff; - } - } - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - if (expected[i][j] != unpacked[i][j]) { - success = FALSE; - } - } - } - - if (!success) { - print_unpacked_z_32unorm(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_z_32unorm(format_desc, " ", expected, " expected\n"); - } - - return success; -} - - -static boolean -test_format_pack_z_32unorm(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint32_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH]; - uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; - unsigned i, j; - boolean success; - - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - unpacked[i][j] = test->unpacked[i][j][0] * 0xffffffff; - if (test->unpacked[i][j][1]) { - return TRUE; - } - } - } - - memset(packed, 0, sizeof packed); - - format_desc->pack_z_32unorm(packed, 0, - &unpacked[0][0], sizeof unpacked[0], - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.bits/8; ++i) - if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) - success = FALSE; - - if (!success) { - print_packed(format_desc, "FAILED: ", packed, " obtained\n"); - print_packed(format_desc, " ", test->packed, " expected\n"); - } - - return success; -} - - -static boolean -test_format_unpack_s_8uscaled(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH] = { { 0 } }; - uint8_t expected[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH] = { { 0 } }; - unsigned i, j; - boolean success; - - format_desc->unpack_s_8uscaled(&unpacked[0][0], sizeof unpacked[0], - test->packed, 0, - format_desc->block.width, format_desc->block.height); - - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - expected[i][j] = test->unpacked[i][j][1]; - } - } - - success = TRUE; - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - if (expected[i][j] != unpacked[i][j]) { - success = FALSE; - } - } - } - - if (!success) { - print_unpacked_s_8uscaled(format_desc, "FAILED: ", unpacked, " obtained\n"); - print_unpacked_s_8uscaled(format_desc, " ", expected, " expected\n"); - } - - return success; -} - - -static boolean -test_format_pack_s_8uscaled(const struct util_format_description *format_desc, - const struct util_format_test_case *test) -{ - uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH]; - uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; - unsigned i, j; - boolean success; - - for (i = 0; i < format_desc->block.height; ++i) { - for (j = 0; j < format_desc->block.width; ++j) { - unpacked[i][j] = test->unpacked[i][j][1]; - if (test->unpacked[i][j][0]) { - return TRUE; - } - } - } - - memset(packed, 0, sizeof packed); - - format_desc->pack_s_8uscaled(packed, 0, - &unpacked[0][0], sizeof unpacked[0], - format_desc->block.width, format_desc->block.height); - - success = TRUE; - for (i = 0; i < format_desc->block.bits/8; ++i) - if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) - success = FALSE; - - if (!success) { - print_packed(format_desc, "FAILED: ", packed, " obtained\n"); - print_packed(format_desc, " ", test->packed, " expected\n"); - } - - return success; -} - - -typedef boolean -(*test_func_t)(const struct util_format_description *format_desc, - const struct util_format_test_case *test); - - -static boolean -test_one_func(const struct util_format_description *format_desc, - test_func_t func, - const char *suffix) -{ - unsigned i; - bool success = TRUE; - - printf("Testing util_format_%s_%s ...\n", - format_desc->short_name, suffix); - fflush(stdout); - - for (i = 0; i < util_format_nr_test_cases; ++i) { - const struct util_format_test_case *test = &util_format_test_cases[i]; - - if (test->format == format_desc->format) { - if (!func(format_desc, &util_format_test_cases[i])) { - success = FALSE; - } - } - } - - return success; -} - - -static boolean -test_all(void) -{ - enum pipe_format format; - bool success = TRUE; - - for (format = 1; format < PIPE_FORMAT_COUNT; ++format) { - const struct util_format_description *format_desc; - - format_desc = util_format_description(format); - if (!format_desc) { - continue; - } - - if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC && - !util_format_s3tc_enabled) { - continue; - } - -# define TEST_ONE_FUNC(name) \ - if (format_desc->name) { \ - if (!test_one_func(format_desc, &test_format_##name, #name)) { \ - success = FALSE; \ - } \ - } - - TEST_ONE_FUNC(fetch_rgba_float); - TEST_ONE_FUNC(pack_rgba_float); - TEST_ONE_FUNC(unpack_rgba_float); - TEST_ONE_FUNC(pack_rgba_8unorm); - TEST_ONE_FUNC(unpack_rgba_8unorm); - - TEST_ONE_FUNC(unpack_z_32unorm); - TEST_ONE_FUNC(pack_z_32unorm); - TEST_ONE_FUNC(unpack_z_float); - TEST_ONE_FUNC(pack_z_float); - TEST_ONE_FUNC(unpack_s_8uscaled); - TEST_ONE_FUNC(pack_s_8uscaled); - -# undef TEST_ONE_FUNC - } - - return success; -} - - -int main(int argc, char **argv) -{ - boolean success; - - util_format_s3tc_init(); - - success = test_all(); - - return success ? 0 : 1; -} diff --git a/src/gallium/tests/unit/u_half_test.c b/src/gallium/tests/unit/u_half_test.c deleted file mode 100644 index 00bda7f50a6..00000000000 --- a/src/gallium/tests/unit/u_half_test.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <float.h> - -#include "util/u_math.h" -#include "util/u_half.h" - -int -main(int argc, char **argv) -{ - unsigned i; - unsigned roundtrip_fails = 0; - for(i = 0; i < 1 << 16; ++i) - { - uint16_t h = (uint16_t) i; - union fi f; - uint16_t rh; - f.ui = util_half_to_floatui(h); - rh = util_floatui_to_half(f.ui); - if(h != rh) - { - printf("Roundtrip failed: %x -> %x = %f -> %x\n", h, f.ui, f.f, rh); - ++roundtrip_fails; - } - } - - if(roundtrip_fails) - printf("Failure! %u/65536 half floats failed a conversion to float and back.\n", roundtrip_fails); - else - printf("Success!\n"); - return 0; -} diff --git a/src/gallium/winsys/g3dvl/Makefile b/src/gallium/winsys/g3dvl/Makefile new file mode 100644 index 00000000000..6c793e0f15b --- /dev/null +++ b/src/gallium/winsys/g3dvl/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/Makefile +TOP = ../../../.. +include $(TOP)/configs/current + +SUBDIRS = $(GALLIUM_STATE_TRACKERS_DIRS) $(GALLIUM_WINSYS_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/winsys/g3dvl/dri/Makefile b/src/gallium/winsys/g3dvl/dri/Makefile new file mode 100644 index 00000000000..b270e780fec --- /dev/null +++ b/src/gallium/winsys/g3dvl/dri/Makefile @@ -0,0 +1,15 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = vldri + +LIBRARY_INCLUDES = -I$(TOP)/src/gallium/winsys/g3dvl \ + $(shell pkg-config libdrm --cflags-only-I) + +C_SOURCES = \ + driclient.c \ + XF86dri.c \ + dri2.c \ + dri_winsys.c + +include ../../../Makefile.template diff --git a/src/driclient/src/XF86dri.c b/src/gallium/winsys/g3dvl/dri/XF86dri.c index 831a7603396..831a7603396 100644 --- a/src/driclient/src/XF86dri.c +++ b/src/gallium/winsys/g3dvl/dri/XF86dri.c diff --git a/src/gallium/winsys/g3dvl/dri/dri2.c b/src/gallium/winsys/g3dvl/dri/dri2.c new file mode 100644 index 00000000000..23fb7780882 --- /dev/null +++ b/src/gallium/winsys/g3dvl/dri/dri2.c @@ -0,0 +1,669 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg ([email protected]) + */ + + +#define NEED_REPLIES +#include <stdio.h> +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include <X11/extensions/dri2proto.h> +#include "xf86drm.h" +#include "dri2.h" +#if 0 +#include "glxclient.h" +#include "GL/glxext.h" +#endif + +/* Allow the build to work with an older versions of dri2proto.h and + * dri2tokens.h. + */ +#if DRI2_MINOR < 1 +#undef DRI2_MINOR +#define DRI2_MINOR 1 +#define X_DRI2GetBuffersWithFormat 7 +#endif + + +static char dri2ExtensionName[] = DRI2_NAME; +static XExtensionInfo *dri2Info; +static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) + +static Bool +DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire); +static Status +DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire); + +static /* const */ XExtensionHooks dri2ExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + DRI2CloseDisplay, /* close_display */ + DRI2WireToEvent, /* wire_to_event */ + DRI2EventToWire, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, + dri2Info, + dri2ExtensionName, + &dri2ExtensionHooks, + 0, NULL) + +static Bool +DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ +#if 0 + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + XExtDisplayInfo *glx_info = __glXFindDisplay(dpy); + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { + +#ifdef X_DRI2SwapBuffers + case DRI2_BufferSwapComplete: + { + GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; + xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire; + aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); + aevent->type = + (glx_info->codes->first_event + GLX_BufferSwapComplete) & 0x75; + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; + aevent->drawable = awire->drawable; + switch (awire->event_type) { + case DRI2_EXCHANGE_COMPLETE: + aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL; + break; + case DRI2_BLIT_COMPLETE: + aevent->event_type = GLX_BLIT_COMPLETE_INTEL; + break; + case DRI2_FLIP_COMPLETE: + aevent->event_type = GLX_FLIP_COMPLETE_INTEL; + break; + default: + /* unknown swap completion type */ + return False; + } + aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; + aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; + aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; + return True; + } +#endif +#ifdef DRI2_InvalidateBuffers + case DRI2_InvalidateBuffers: + { + xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; + + dri2InvalidateBuffers(dpy, awire->drawable); + return False; + } +#endif + default: + /* client doesn't support server event */ + break; + } +#endif + return False; +} + +/* We don't actually support this. It doesn't make sense for clients to + * send each other DRI2 events. + */ +static Status +DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + switch (event->type) { + default: + /* client doesn't support server event */ + break; + } + + return Success; +} + +Bool +DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + if (XextHasExtension(info)) { + *eventBase = info->codes->first_event; + *errorBase = info->codes->first_error; + return True; + } + + return False; +} + +Bool +DRI2QueryVersion(Display * dpy, int *major, int *minor) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2QueryVersionReply rep; + xDRI2QueryVersionReq *req; + int i, nevents; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2QueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2QueryVersion; + req->majorVersion = DRI2_MAJOR; + req->minorVersion = DRI2_MINOR; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *major = rep.majorVersion; + *minor = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + + switch (rep.minorVersion) { + case 1: + nevents = 0; + break; + case 2: + nevents = 1; + break; + case 3: + default: + nevents = 2; + break; + } + + for (i = 0; i < nevents; i++) { + XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent); + XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire); + } + + return True; +} + +Bool +DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ConnectReply rep; + xDRI2ConnectReq *req; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Connect, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Connect; + req->window = window; + req->driverType = DRI2DriverDRI; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *driverName = Xmalloc(rep.driverNameLength + 1); + if (*driverName == NULL) { + _XEatData(dpy, + ((rep.driverNameLength + 3) & ~3) + + ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *driverName, rep.driverNameLength); + (*driverName)[rep.driverNameLength] = '\0'; + + *deviceName = Xmalloc(rep.deviceNameLength + 1); + if (*deviceName == NULL) { + Xfree(*driverName); + _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *deviceName, rep.deviceNameLength); + (*deviceName)[rep.deviceNameLength] = '\0'; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +Bool +DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2AuthenticateReq *req; + xDRI2AuthenticateReply rep; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Authenticate, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Authenticate; + req->window = window; + req->magic = magic; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return rep.authenticated; +} + +void +DRI2CreateDrawable(Display * dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CreateDrawableReq *req; + + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2CreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CreateDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + +void +DRI2DestroyDrawable(Display * dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2DestroyDrawableReq *req; + + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); + + XSync(dpy, False); + + LockDisplay(dpy); + GetReq(DRI2DestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2DestroyDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + +DRI2Buffer * +DRI2GetBuffers(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, int *outCount) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetBuffersReply rep; + xDRI2GetBuffersReq *req; + DRI2Buffer *buffers; + xDRI2Buffer repBuffer; + CARD32 *p; + int i; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReqExtra(DRI2GetBuffers, count * 4, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetBuffers; + req->drawable = drawable; + req->count = count; + p = (CARD32 *) & req[1]; + for (i = 0; i < count; i++) + p[i] = attachments[i]; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + *width = rep.width; + *height = rep.height; + *outCount = rep.count; + + buffers = Xmalloc(rep.count * sizeof buffers[0]); + if (buffers == NULL) { + _XEatData(dpy, rep.count * sizeof repBuffer); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + for (i = 0; i < rep.count; i++) { + _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); + buffers[i].attachment = repBuffer.attachment; + buffers[i].name = repBuffer.name; + buffers[i].pitch = repBuffer.pitch; + buffers[i].cpp = repBuffer.cpp; + buffers[i].flags = repBuffer.flags; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return buffers; +} + + +DRI2Buffer * +DRI2GetBuffersWithFormat(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, int *outCount) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetBuffersReply rep; + xDRI2GetBuffersReq *req; + DRI2Buffer *buffers; + xDRI2Buffer repBuffer; + CARD32 *p; + int i; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetBuffersWithFormat; + req->drawable = drawable; + req->count = count; + p = (CARD32 *) & req[1]; + for (i = 0; i < (count * 2); i++) + p[i] = attachments[i]; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + *width = rep.width; + *height = rep.height; + *outCount = rep.count; + + buffers = Xmalloc(rep.count * sizeof buffers[0]); + if (buffers == NULL) { + _XEatData(dpy, rep.count * sizeof repBuffer); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + for (i = 0; i < rep.count; i++) { + _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); + buffers[i].attachment = repBuffer.attachment; + buffers[i].name = repBuffer.name; + buffers[i].pitch = repBuffer.pitch; + buffers[i].cpp = repBuffer.cpp; + buffers[i].flags = repBuffer.flags; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return buffers; +} + + +void +DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, + CARD32 dest, CARD32 src) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CopyRegionReq *req; + xDRI2CopyRegionReply rep; + + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2CopyRegion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CopyRegion; + req->drawable = drawable; + req->region = region; + req->dest = dest; + req->src = src; + + _XReply(dpy, (xReply *) & rep, 0, xFalse); + + UnlockDisplay(dpy); + SyncHandle(); +} + +#ifdef X_DRI2SwapBuffers +static void +load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor, + CARD64 remainder) +{ + req->target_msc_hi = target >> 32; + req->target_msc_lo = target & 0xffffffff; + req->divisor_hi = divisor >> 32; + req->divisor_lo = divisor & 0xffffffff; + req->remainder_hi = remainder >> 32; + req->remainder_lo = remainder & 0xffffffff; +} + +static CARD64 +vals_to_card64(CARD32 lo, CARD32 hi) +{ + return (CARD64)hi << 32 | lo; +} + +void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, + CARD64 divisor, CARD64 remainder, CARD64 *count) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2SwapBuffersReq *req; + xDRI2SwapBuffersReply rep; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2SwapBuffers, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2SwapBuffers; + req->drawable = drawable; + load_swap_req(req, target_msc, divisor, remainder); + + _XReply(dpy, (xReply *)&rep, 0, xFalse); + + *count = vals_to_card64(rep.swap_lo, rep.swap_hi); + + UnlockDisplay(dpy); + SyncHandle(); +} +#endif + +#ifdef X_DRI2GetMSC +Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, + CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetMSCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2GetMSC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetMSC; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = vals_to_card64(rep.ust_lo, rep.ust_hi); + *msc = vals_to_card64(rep.msc_lo, rep.msc_hi); + *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi); + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} +#endif + +#ifdef X_DRI2WaitMSC +static void +load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor, + CARD64 remainder) +{ + req->target_msc_hi = target >> 32; + req->target_msc_lo = target & 0xffffffff; + req->divisor_hi = divisor >> 32; + req->divisor_lo = divisor & 0xffffffff; + req->remainder_hi = remainder >> 32; + req->remainder_lo = remainder & 0xffffffff; +} + +Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2WaitMSCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2WaitMSC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2WaitMSC; + req->drawable = drawable; + load_msc_req(req, target_msc, divisor, remainder); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo; + *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo; + *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} +#endif + +#ifdef X_DRI2WaitSBC +static void +load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target) +{ + req->target_sbc_hi = target >> 32; + req->target_sbc_lo = target & 0xffffffff; +} + +Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, + CARD64 *msc, CARD64 *sbc) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2WaitSBCReq *req; + xDRI2MSCReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2WaitSBC, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2WaitSBC; + req->drawable = drawable; + load_sbc_req(req, target_sbc); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo; + *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo; + *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} +#endif + +#ifdef X_DRI2SwapInterval +void DRI2SwapInterval(Display *dpy, XID drawable, int interval) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2SwapIntervalReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2SwapInterval, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2SwapInterval; + req->drawable = drawable; + req->interval = interval; + UnlockDisplay(dpy); + SyncHandle(); +} +#endif diff --git a/src/gallium/winsys/g3dvl/dri/dri2.h b/src/gallium/winsys/g3dvl/dri/dri2.h new file mode 100644 index 00000000000..114e9f8f965 --- /dev/null +++ b/src/gallium/winsys/g3dvl/dri/dri2.h @@ -0,0 +1,106 @@ +/* + * Copyright © 2007,2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg ([email protected]) + */ + +#ifndef _DRI2_H_ +#define _DRI2_H_ + +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/dri2tokens.h> + +typedef struct +{ + unsigned int attachment; + unsigned int name; + unsigned int pitch; + unsigned int cpp; + unsigned int flags; +} DRI2Buffer; + +extern Bool +DRI2QueryExtension(Display * display, int *eventBase, int *errorBase); + +extern Bool +DRI2QueryVersion(Display * display, int *major, int *minor); + +extern Bool +DRI2Connect(Display * display, XID window, + char **driverName, char **deviceName); + +extern Bool +DRI2Authenticate(Display * display, XID window, drm_magic_t magic); + +extern void +DRI2CreateDrawable(Display * display, XID drawable); + +extern void +DRI2DestroyDrawable(Display * display, XID handle); + +extern DRI2Buffer* +DRI2GetBuffers(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, + int *outCount); + +/** + * \note + * This function is only supported with DRI2 version 1.1 or later. + */ +extern DRI2Buffer* +DRI2GetBuffersWithFormat(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, + int count, int *outCount); + +extern void +DRI2CopyRegion(Display * dpy, XID drawable, + XserverRegion region, + CARD32 dest, CARD32 src); + +extern void +DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *count); + +extern Bool +DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc); + +extern Bool +DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, + CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc); + +extern Bool +DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, + CARD64 *msc, CARD64 *sbc); + +extern void +DRI2SwapInterval(Display *dpy, XID drawable, int interval); + +#endif diff --git a/src/gallium/winsys/g3dvl/dri/dri_winsys.c b/src/gallium/winsys/g3dvl/dri/dri_winsys.c new file mode 100644 index 00000000000..8588ddd17cb --- /dev/null +++ b/src/gallium/winsys/g3dvl/dri/dri_winsys.c @@ -0,0 +1,282 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vl_winsys.h> +#include <driclient.h> +#include <pipe/p_video_context.h> +#include <pipe/p_state.h> +#include <util/u_memory.h> +#include <util/u_hash.h> +#include <util/u_hash_table.h> +#include <state_tracker/drm_driver.h> +#include <X11/Xlibint.h> + +struct vl_dri_screen +{ + struct vl_screen base; + dri_screen_t *dri_screen; + struct util_hash_table *drawable_table; + Drawable last_seen_drawable; +}; + +struct vl_dri_context +{ + struct vl_context base; + int fd; +}; + +static struct pipe_surface* +vl_dri2_get_front(struct vl_context *vctx, Drawable drawable) +{ + int w, h; + unsigned int attachments[1] = {DRI_BUFFER_FRONT_LEFT}; + int count; + DRI2Buffer *dri2_front; + struct pipe_resource *front_tex; + struct pipe_surface *front_surf = NULL; + + assert(vctx); + + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vctx->vscreen; + assert(vl_dri_scrn); + + dri2_front = DRI2GetBuffers(vl_dri_scrn->dri_screen->display, + drawable, &w, &h, attachments, 1, &count); + + assert(count == 1); + + if (dri2_front) { + struct winsys_handle dri2_front_handle = + { + .type = DRM_API_HANDLE_TYPE_SHARED, + .handle = dri2_front->name, + .stride = dri2_front->pitch + }; + struct pipe_resource template; + struct pipe_surface surf_template; + + memset(&template, 0, sizeof(struct pipe_resource)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_B8G8R8X8_UNORM; + template.last_level = 0; + template.width0 = w; + template.height0 = h; + template.depth0 = 1; + template.usage = PIPE_USAGE_STATIC; + template.bind = PIPE_BIND_RENDER_TARGET; + template.flags = 0; + + front_tex = vl_dri_scrn->base.pscreen->resource_from_handle(vl_dri_scrn->base.pscreen, &template, &dri2_front_handle); + if (front_tex) { + memset(&surf_template, 0, sizeof(surf_template)); + surf_template.format = front_tex->format; + surf_template.usage = PIPE_BIND_RENDER_TARGET; + front_surf = vctx->vpipe->create_surface(vctx->vpipe, front_tex, &surf_template); + } + pipe_resource_reference(&front_tex, NULL); + Xfree(dri2_front); + } + + return front_surf; +} + +static void +vl_dri2_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *context_private) +{ + struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)context_private; + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vl_dri_ctx->base.vscreen; + + assert(screen); + assert(resource); + assert(context_private); + + dri2CopyDrawable(vl_dri_scrn->dri_screen, vl_dri_scrn->last_seen_drawable, + DRI_BUFFER_FRONT_LEFT, DRI_BUFFER_FAKE_FRONT_LEFT); +} + +struct pipe_surface* +vl_drawable_surface_get(struct vl_context *vctx, Drawable drawable) +{ + assert(vctx); + + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vctx->vscreen; + assert(vl_dri_scrn); + + if (vl_dri_scrn->last_seen_drawable != drawable) { + /* Hash table business depends on this equality */ + assert(None == NULL); + Drawable lookup_drawable = (Drawable)util_hash_table_get(vl_dri_scrn->drawable_table, (void*)drawable); + if (lookup_drawable == None) { + dri2CreateDrawable(vl_dri_scrn->dri_screen, drawable); + util_hash_table_set(vl_dri_scrn->drawable_table, (void*)drawable, (void*)drawable); + } + vl_dri_scrn->last_seen_drawable = drawable; + } + + return vl_dri2_get_front(vctx, drawable); +} + +void* +vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *displaytarget) +{ + return vctx; +} + +static unsigned drawable_hash(void *key) +{ + Drawable drawable = (Drawable)key; + assert(drawable != None); + return util_hash_crc32(&drawable, sizeof(Drawable)); +} + +static int drawable_cmp(void *key1, void *key2) +{ + Drawable d1 = (Drawable)key1; + Drawable d2 = (Drawable)key2; + assert(d1 != None); + assert(d2 != None); + return d1 != d2; +} + +static enum pipe_error +drawable_destroy(void *key, void *value, void *data) +{ + Drawable drawable = (Drawable)key; + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)data; + + assert(drawable != None); + assert(value); + assert(data); + + dri2DestroyDrawable(vl_dri_scrn->dri_screen, drawable); + + return PIPE_OK; +} + +struct vl_screen* +vl_screen_create(Display *display, int screen) +{ + struct vl_dri_screen *vl_dri_scrn; + + assert(display); + + vl_dri_scrn = CALLOC_STRUCT(vl_dri_screen); + if (!vl_dri_scrn) + goto no_struct; + + if (dri2CreateScreen(display, screen, &vl_dri_scrn->dri_screen)) + goto no_dri2screen; + + vl_dri_scrn->base.pscreen = driver_descriptor.create_screen(vl_dri_scrn->dri_screen->fd); + + if (!vl_dri_scrn->base.pscreen) + goto no_pscreen; + + vl_dri_scrn->drawable_table = util_hash_table_create(&drawable_hash, &drawable_cmp); + if (!vl_dri_scrn->drawable_table) + goto no_hash; + + vl_dri_scrn->last_seen_drawable = None; + vl_dri_scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer; + + return &vl_dri_scrn->base; + +no_hash: + vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen); +no_pscreen: + dri2DestroyScreen(vl_dri_scrn->dri_screen); +no_dri2screen: + FREE(vl_dri_scrn); +no_struct: + return NULL; +} + +void vl_screen_destroy(struct vl_screen *vscreen) +{ + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen; + + assert(vscreen); + + util_hash_table_foreach(vl_dri_scrn->drawable_table, drawable_destroy, vl_dri_scrn); + util_hash_table_destroy(vl_dri_scrn->drawable_table); + vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen); + dri2DestroyScreen(vl_dri_scrn->dri_screen); + FREE(vl_dri_scrn); +} + +struct vl_context* +vl_video_create(struct vl_screen *vscreen, + enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height) +{ + struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen; + struct vl_dri_context *vl_dri_ctx; + + vl_dri_ctx = CALLOC_STRUCT(vl_dri_context); + if (!vl_dri_ctx) + goto no_struct; + + if (!vscreen->pscreen->video_context_create) { + debug_printf("[G3DVL] No video support found on %s/%s.\n", + vscreen->pscreen->get_vendor(vscreen->pscreen), + vscreen->pscreen->get_name(vscreen->pscreen)); + goto no_vpipe; + } + + vl_dri_ctx->base.vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen, + profile, chroma_format, + width, height, + vl_dri_ctx); + + if (!vl_dri_ctx->base.vpipe) + goto no_vpipe; + + vl_dri_ctx->base.vpipe->priv = vl_dri_ctx; + vl_dri_ctx->base.vscreen = vscreen; + vl_dri_ctx->fd = vl_dri_scrn->dri_screen->fd; + + return &vl_dri_ctx->base; + +no_vpipe: + FREE(vl_dri_ctx); +no_struct: + return NULL; +} + +void vl_video_destroy(struct vl_context *vctx) +{ + struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)vctx; + + assert(vctx); + + vl_dri_ctx->base.vpipe->destroy(vl_dri_ctx->base.vpipe); + FREE(vl_dri_ctx); +} diff --git a/src/driclient/src/driclient.c b/src/gallium/winsys/g3dvl/dri/driclient.c index dc2189afec3..90e48a7cb28 100644 --- a/src/driclient/src/driclient.c +++ b/src/gallium/winsys/g3dvl/dri/driclient.c @@ -1,6 +1,8 @@ #include "driclient.h" #include <assert.h> #include <stdlib.h> +#include <fcntl.h> +#include <X11/Xlibint.h> int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf) { @@ -222,12 +224,12 @@ int driUpdateDrawableInfo(dri_drawable_t *dri_drawable) dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable, - &dri_drawable->sarea_index, - &dri_drawable->last_sarea_stamp, - &dri_drawable->x, - &dri_drawable->y, - &dri_drawable->w, - &dri_drawable->h, + &dri_drawable->sarea_index, + &dri_drawable->last_sarea_stamp, + &dri_drawable->x, + &dri_drawable->y, + &dri_drawable->w, + &dri_drawable->h, &dri_drawable->num_cliprects, &dri_drawable->cliprects, &dri_drawable->back_x, @@ -308,3 +310,79 @@ int driDestroyContext(dri_context_t *dri_context) return 0; } + +int dri2CreateScreen(Display *display, int screen, dri_screen_t **dri_screen) +{ + dri_screen_t *dri_scrn; + drm_magic_t magic; + char *drvName; + char *devName; + + dri_scrn = calloc(1, sizeof(dri_screen_t)); + + if (!dri_scrn) + return 1; + + if (!DRI2Connect(display, XRootWindow(display, screen), &drvName, &devName)) + goto free_screen; + + dri_scrn->fd = open(devName, O_RDWR); + Xfree(drvName); + Xfree(devName); + if (dri_scrn->fd < 0) + goto free_screen; + + if (drmGetMagic(dri_scrn->fd, &magic)) + goto free_screen; + + if (!DRI2Authenticate(display, RootWindow(display, screen), magic)) + goto free_screen; + + dri_scrn->display = display; + dri_scrn->num = screen; + *dri_screen = dri_scrn; + + return 0; + +free_screen: + free(dri_scrn); + + return 1; +} + +int dri2DestroyScreen(dri_screen_t *dri_screen) +{ + /* Not much to do here apparently... */ + assert(dri_screen); + free(dri_screen); + return 0; +} + +int dri2CreateDrawable(dri_screen_t *dri_screen, XID drawable) +{ + assert(dri_screen); + DRI2CreateDrawable(dri_screen->display, drawable); + return 0; +} + +int dri2DestroyDrawable(dri_screen_t *dri_screen, XID drawable) +{ + assert(dri_screen); + DRI2DestroyDrawable(dri_screen->display, drawable); + return 0; +} + +int dri2CopyDrawable(dri_screen_t *dri_screen, XID drawable, int dest, int src) +{ + XserverRegion region; + + assert(dri_screen); + assert(dest >= DRI_BUFFER_FRONT_LEFT && dest <= DRI_BUFFER_DEPTH_STENCIL); + assert(src >= DRI_BUFFER_FRONT_LEFT && src <= DRI_BUFFER_DEPTH_STENCIL); + + region = XFixesCreateRegionFromWindow(dri_screen->display, drawable, WindowRegionBounding); + DRI2CopyRegion(dri_screen->display, drawable, region, dest, src); + XFixesDestroyRegion(dri_screen->display, region); + + return 0; +} diff --git a/src/driclient/include/driclient.h b/src/gallium/winsys/g3dvl/dri/driclient.h index d3915250392..4e4fd362395 100644 --- a/src/driclient/include/driclient.h +++ b/src/gallium/winsys/g3dvl/dri/driclient.h @@ -2,9 +2,12 @@ #define driclient_h #include <stdint.h> +#include <X11/Xmd.h> #include <X11/Xlib.h> #include <drm_sarea.h> +//#include <X11/extensions/dri2proto.h> #include "xf86dri.h" +#include "dri2.h" /* TODO: Bring in DRI XML options */ @@ -93,5 +96,22 @@ do \ } \ } while (0) +int dri2CreateScreen(Display *display, int screen, dri_screen_t **dri_screen); +int dri2DestroyScreen(dri_screen_t *dri_screen); +int dri2CreateDrawable(dri_screen_t *dri_screen, XID drawable); +int dri2DestroyDrawable(dri_screen_t *dri_screen, XID drawable); +int dri2CopyDrawable(dri_screen_t *dri_screen, XID drawable, int dest, int src); + +#define DRI_BUFFER_FRONT_LEFT 0 +#define DRI_BUFFER_BACK_LEFT 1 +#define DRI_BUFFER_FRONT_RIGHT 2 +#define DRI_BUFFER_BACK_RIGHT 3 +#define DRI_BUFFER_DEPTH 4 +#define DRI_BUFFER_STENCIL 5 +#define DRI_BUFFER_ACCUM 6 +#define DRI_BUFFER_FAKE_FRONT_LEFT 7 +#define DRI_BUFFER_FAKE_FRONT_RIGHT 8 +#define DRI_BUFFER_DEPTH_STENCIL 9 /**< Only available with DRI2 1.1 */ + #endif diff --git a/src/driclient/include/xf86dri.h b/src/gallium/winsys/g3dvl/dri/xf86dri.h index baf80a7a9dd..baf80a7a9dd 100644 --- a/src/driclient/include/xf86dri.h +++ b/src/gallium/winsys/g3dvl/dri/xf86dri.h diff --git a/src/driclient/src/xf86dristr.h b/src/gallium/winsys/g3dvl/dri/xf86dristr.h index b834bd1a1a0..b834bd1a1a0 100644 --- a/src/driclient/src/xf86dristr.h +++ b/src/gallium/winsys/g3dvl/dri/xf86dristr.h diff --git a/src/gallium/winsys/g3dvl/drm/Makefile b/src/gallium/winsys/g3dvl/drm/Makefile new file mode 100644 index 00000000000..0711f44d8e3 --- /dev/null +++ b/src/gallium/winsys/g3dvl/drm/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/Makefile +TOP = ../../../../.. +include $(TOP)/configs/current + +SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/winsys/g3dvl/drm/Makefile.template b/src/gallium/winsys/g3dvl/drm/Makefile.template new file mode 100644 index 00000000000..2b79deef4bc --- /dev/null +++ b/src/gallium/winsys/g3dvl/drm/Makefile.template @@ -0,0 +1,66 @@ +XVMC_MAJOR = 1 +XVMC_MINOR = 0 +XVMC_LIB = XvMCg3dvl +XVMC_LIB_NAME = lib$(XVMC_LIB).so +XVMC_LIB_DEPS = $(EXTRA_LIB_PATH) -lXvMC -lXv -lX11 -lm + +############################################################### + +INCLUDES = $(DRIVER_INCLUDES) \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/winsys/g3dvl \ + -I$(TOP)/src/gallium/winsys/g3dvl/dri + +DEFINES += $(DRIVER_DEFINES) \ + -DGALLIUM_SOFTPIPE \ + -DGALLIUM_TRACE + +# XXX: Hack, if we include libxvmctracker.a in LIBS none of the symbols are +# pulled in by the linker because xsp_winsys.c doesn't refer to them +OBJECTS = $(C_SOURCES:.c=.o) $(TOP)/src/gallium/state_trackers/xorg/xvmc/*.o + +LIBS = $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \ + $(PIPE_DRIVERS) \ + $(TOP)/src/gallium/auxiliary/libgallium.a + +.c.o: + $(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ + +.PHONY: default $(TOP)/$(LIB_DIR)/gallium clean + +default: depend $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME) + +$(TOP)/$(LIB_DIR)/gallium: + @mkdir -p $(TOP)/$(LIB_DIR)/gallium + +# Make the libXvMCg3dvl.so library +$(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME): $(OBJECTS) $(LIBS) Makefile + $(MKLIB) -o $(XVMC_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(XVMC_MAJOR) -minor $(XVMC_MINOR) $(MKLIB_OPTIONS) \ + -install $(TOP)/$(LIB_DIR)/gallium -id $(INSTALL_LIB_DIR)/lib$(XVMC_LIB).1.dylib \ + $(XVMC_LIB_DEPS) $(DRIVER_LIB_DEPS) $(OBJECTS) $(LIBS) + +depend: $(SOURCES) Makefile + $(RM) depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(SOURCES) + +#install: default +# $(INSTALL) -d $(INSTALL_DIR)/include/GL +# $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) +# $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL +# @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ +# $(INSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \ +# fi + +clean: Makefile + $(RM) $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME) + $(RM) *.o *~ + $(RM) depend depend.bak + +-include depend diff --git a/src/gallium/winsys/g3dvl/drm/nouveau/Makefile b/src/gallium/winsys/g3dvl/drm/nouveau/Makefile new file mode 100644 index 00000000000..5c55186f672 --- /dev/null +++ b/src/gallium/winsys/g3dvl/drm/nouveau/Makefile @@ -0,0 +1,23 @@ +# This makefile produces a libXvMCg3dvl.so which is +# based on DRM/DRI + +TOP = ../../../../../.. +include $(TOP)/configs/current + +C_SOURCES = + +DRIVER_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I) \ + -I$(TOP)/src/gallium/winsys/drm/nouveau +DRIVER_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other) + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ + $(TOP)/src/gallium/drivers/nv30/libnv30.a \ + $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nv50/libnv50.a \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +DRIVER_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs) + +include ../Makefile.template diff --git a/src/gallium/winsys/g3dvl/drm/radeon/Makefile b/src/gallium/winsys/g3dvl/drm/radeon/Makefile new file mode 100644 index 00000000000..0f7fd1c15ad --- /dev/null +++ b/src/gallium/winsys/g3dvl/drm/radeon/Makefile @@ -0,0 +1,20 @@ +# This makefile produces a libXvMCg3dvl.so which is +# based on DRM/DRI + +TOP = ../../../../../.. +include $(TOP)/configs/current + +C_SOURCES = + +DRIVER_INCLUDES = $(shell pkg-config libdrm libdrm_radeon --cflags-only-I) \ + -I$(TOP)/src/gallium/winsys/drm/radeon \ +DRIVER_DEFINES = $(shell pkg-config libdrm libdrm_radeon --cflags-only-other) + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ + $(TOP)/src/gallium/drivers/r300/libr300.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +DRIVER_LIB_DEPS += $(shell pkg-config libdrm_radeon --libs) + +include ../Makefile.template diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h new file mode 100644 index 00000000000..58f548849f6 --- /dev/null +++ b/src/gallium/winsys/g3dvl/vl_winsys.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef vl_winsys_h +#define vl_winsys_h + +#include <X11/Xlib.h> +#include <pipe/p_defines.h> +#include <pipe/p_format.h> + +struct pipe_screen; +struct pipe_video_context; +struct pipe_surface; + +struct vl_screen +{ + struct pipe_screen *pscreen; +}; + +struct vl_context +{ + struct vl_screen *vscreen; + struct pipe_video_context *vpipe; +}; + +struct vl_screen* +vl_screen_create(Display *display, int screen); + +void vl_screen_destroy(struct vl_screen *vscreen); + +struct vl_context* +vl_video_create(struct vl_screen *vscreen, + enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height); + +void vl_video_destroy(struct vl_context *vctx); + +struct pipe_surface* +vl_drawable_surface_get(struct vl_context *vctx, Drawable drawable); + +void* +vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *drawable_surface); + +#endif diff --git a/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c b/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c new file mode 100644 index 00000000000..cc80583f088 --- /dev/null +++ b/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c @@ -0,0 +1,202 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vl_winsys.h> +#include <X11/Xlibint.h> +#include <state_tracker/xlib_sw_winsys.h> +#include <util/u_memory.h> +#include <util/u_format.h> +#include <softpipe/sp_public.h> +#include <softpipe/sp_video_context.h> + +struct vl_xsp_screen +{ + struct vl_screen base; + Display *display; + int screen; + Visual visual; + struct xlib_drawable xdraw; + struct pipe_surface *drawable_surface; +}; + +struct pipe_surface* +vl_drawable_surface_get(struct vl_screen *vscreen, Drawable drawable) +{ + struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen; + Window root; + int x, y; + unsigned int width, height; + unsigned int border_width; + unsigned int depth; + struct pipe_resource templat, *drawable_tex; + struct pipe_surface *drawable_surface = NULL; + + assert(vscreen); + assert(drawable != None); + + if (XGetGeometry(xsp_screen->display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable) + return NULL; + + xsp_screen->xdraw.drawable = drawable; + + if (xsp_screen->drawable_surface) { + if (xsp_screen->drawable_surface->width == width && + xsp_screen->drawable_surface->height == height) { + pipe_surface_reference(&drawable_surface, xsp_screen->drawable_surface); + return drawable_surface; + } + else + pipe_surface_reference(&xsp_screen->drawable_surface, NULL); + } + + memset(&templat, 0, sizeof(struct pipe_resource)); + templat.target = PIPE_TEXTURE_2D; + /* XXX: Need to figure out drawable's format */ + templat.format = PIPE_FORMAT_B8G8R8X8_UNORM; + templat.last_level = 0; + templat.width0 = width; + templat.height0 = height; + templat.depth0 = 1; + templat.usage = PIPE_USAGE_DEFAULT; + templat.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET; + templat.flags = 0; + + drawable_tex = vscreen->pscreen->resource_create(vscreen->pscreen, &templat); + if (!drawable_tex) + return NULL; + + xsp_screen->drawable_surface = vscreen->pscreen->get_tex_surface(vscreen->pscreen, drawable_tex, + 0, 0, 0, + templat.bind); + pipe_resource_reference(&drawable_tex, NULL); + + if (!xsp_screen->drawable_surface) + return NULL; + + pipe_surface_reference(&drawable_surface, xsp_screen->drawable_surface); + + xsp_screen->xdraw.depth = 24/*util_format_get_blocksizebits(templat.format) / + util_format_get_blockwidth(templat.format)*/; + + return drawable_surface; +} + +void* +vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *drawable_surface) +{ + struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vctx->vscreen; + + assert(vctx); + assert(drawable_surface); + assert(xsp_screen->drawable_surface == drawable_surface); + + return &xsp_screen->xdraw; +} + +struct vl_screen* +vl_screen_create(Display *display, int screen) +{ + struct vl_xsp_screen *xsp_screen; + struct sw_winsys *winsys; + + assert(display); + + xsp_screen = CALLOC_STRUCT(vl_xsp_screen); + if (!xsp_screen) + return NULL; + + winsys = xlib_create_sw_winsys(display); + if (!winsys) { + FREE(xsp_screen); + return NULL; + } + + xsp_screen->base.pscreen = softpipe_create_screen(winsys); + if (!xsp_screen->base.pscreen) { + winsys->destroy(winsys); + FREE(xsp_screen); + return NULL; + } + + xsp_screen->display = display; + xsp_screen->screen = screen; + xsp_screen->xdraw.visual = XDefaultVisual(display, screen); + + return &xsp_screen->base; +} + +void vl_screen_destroy(struct vl_screen *vscreen) +{ + struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen; + + assert(vscreen); + + pipe_surface_reference(&xsp_screen->drawable_surface, NULL); + vscreen->pscreen->destroy(vscreen->pscreen); + FREE(vscreen); +} + +struct vl_context* +vl_video_create(struct vl_screen *vscreen, + enum pipe_video_profile profile, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height) +{ + struct pipe_video_context *vpipe; + struct vl_context *vctx; + + assert(vscreen); + assert(width && height); + assert(vscreen->pscreen->video_context_create); + + vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen, + profile, + chroma_format, + width, height, NULL); + if (!vpipe) + return NULL; + + vctx = CALLOC_STRUCT(vl_context); + if (!vctx) { + vpipe->destroy(vpipe); + return NULL; + } + + vpipe->priv = vctx; + vctx->vpipe = vpipe; + vctx->vscreen = vscreen; + + return vctx; +} + +void vl_video_destroy(struct vl_context *vctx) +{ + assert(vctx); + + vctx->vpipe->destroy(vctx->vpipe); + FREE(vctx); +} diff --git a/src/gallium/winsys/r600/drm/r600_bo.c b/src/gallium/winsys/r600/drm/r600_bo.c index 6a3737f0a4a..339d5dc47f4 100644 --- a/src/gallium/winsys/r600/drm/r600_bo.c +++ b/src/gallium/winsys/r600/drm/r600_bo.c @@ -63,12 +63,25 @@ struct r600_bo *r600_bo(struct radeon *radeon, * and are used for uploads and downloads from regular * resources. We generate them internally for some transfers. */ - if (usage == PIPE_USAGE_STAGING) - bo->domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT; - else - bo->domains = (RADEON_GEM_DOMAIN_CPU | + switch (usage) { + case PIPE_USAGE_DEFAULT: + bo->domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT | - RADEON_GEM_DOMAIN_VRAM); + RADEON_GEM_DOMAIN_VRAM; + break; + + case PIPE_USAGE_DYNAMIC: + case PIPE_USAGE_STREAM: + case PIPE_USAGE_STAGING: + bo->domains = RADEON_GEM_DOMAIN_CPU | + RADEON_GEM_DOMAIN_GTT; + break; + + case PIPE_USAGE_STATIC: + case PIPE_USAGE_IMMUTABLE: + bo->domains = RADEON_GEM_DOMAIN_VRAM; + break; + } pipe_reference_init(&bo->reference, 1); return bo; |