summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r--src/gallium/state_trackers/egl/egl_surface.c7
-rw-r--r--src/gallium/state_trackers/egl/egl_tracker.h1
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_basic_csc.c12
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc14
-rw-r--r--src/gallium/state_trackers/python/st_softpipe_winsys.c1
-rw-r--r--src/gallium/state_trackers/wgl/SConscript25
-rw-r--r--src/gallium/state_trackers/wgl/opengl32.def1
-rw-r--r--src/gallium/state_trackers/wgl/opengl32.mingw.def1
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_context.c382
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_public.h73
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.c (renamed from src/gallium/state_trackers/wgl/icd/stw_icd.c)478
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.h (renamed from src/gallium/state_trackers/wgl/shared/stw_context.h)8
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.c (renamed from src/gallium/state_trackers/wgl/shared/stw_device.c)85
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.h (renamed from src/gallium/state_trackers/wgl/shared/stw_device.h)9
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c (renamed from src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_gallium.c (renamed from src/gallium/state_trackers/wgl/shared/stw_extgallium.c)2
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_gallium.h (renamed from src/gallium/state_trackers/wgl/shared/stw_extgallium.h)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_pixelformat.c (renamed from src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c)1
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_swapinterval.c (renamed from src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.c (renamed from src/gallium/state_trackers/wgl/shared/stw_framebuffer.c)208
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.h (renamed from src/gallium/state_trackers/wgl/shared/stw_framebuffer.h)16
-rw-r--r--src/gallium/state_trackers/wgl/stw_getprocaddress.c (renamed from src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c)7
-rw-r--r--src/gallium/state_trackers/wgl/stw_icd.h (renamed from src/gallium/state_trackers/wgl/icd/stw_icd.h)114
-rw-r--r--src/gallium/state_trackers/wgl/stw_pixelformat.c (renamed from src/gallium/state_trackers/wgl/shared/stw_pixelformat.c)67
-rw-r--r--src/gallium/state_trackers/wgl/stw_pixelformat.h (renamed from src/gallium/state_trackers/wgl/shared/stw_pixelformat.h)11
-rw-r--r--src/gallium/state_trackers/wgl/stw_tls.c (renamed from src/gallium/state_trackers/wgl/shared/stw_tls.c)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_tls.h (renamed from src/gallium/state_trackers/wgl/shared/stw_tls.h)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_wgl.c (renamed from src/gallium/state_trackers/wgl/wgl/stw_wgl.c)63
-rw-r--r--src/gallium/state_trackers/wgl/stw_wgl.h (renamed from src/gallium/state_trackers/wgl/wgl/stw_wgl.h)0
-rw-r--r--src/gallium/state_trackers/wgl/stw_winsys.h (renamed from src/gallium/state_trackers/wgl/shared/stw_winsys.h)54
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c636
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.h12
-rw-r--r--src/gallium/state_trackers/xorg/xorg_crtc.c4
-rw-r--r--src/gallium/state_trackers/xorg/xorg_dri2.c1
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c1
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c315
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h27
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c55
-rw-r--r--src/gallium/state_trackers/xorg/xorg_output.c4
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h7
-rw-r--r--src/gallium/state_trackers/xorg/xorg_xv.c212
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/Makefile16
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/SConscript27
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/attributes.c19
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/block.c61
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/context.c214
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/subpicture.c168
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/surface.c382
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/.gitignore5
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/Makefile28
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c84
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_context.c92
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c290
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c71
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/testlib.c119
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/testlib.h42
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c273
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/xvmc_private.h31
58 files changed, 3861 insertions, 975 deletions
diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c
index 69e2d6b708..542ac56121 100644
--- a/src/gallium/state_trackers/egl/egl_surface.c
+++ b/src/gallium/state_trackers/egl/egl_surface.c
@@ -152,7 +152,6 @@ drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen)
pipe_surface_reference(&screen->surface, NULL);
pipe_texture_reference(&screen->tex, NULL);
- pipe_buffer_reference(&screen->buffer, NULL);
screen->shown = 0;
}
@@ -250,8 +249,8 @@ drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy,
drm_create_texture(dpy, scrn, mode->Width, mode->Height);
- if (!scrn->buffer)
- return EGL_FALSE;
+ if (!scrn->tex)
+ goto err_tex;
ret = drmModeAddFB(dev->drmFD,
scrn->front.width, scrn->front.height,
@@ -325,8 +324,8 @@ err_fb:
err_bo:
pipe_surface_reference(&scrn->surface, NULL);
pipe_texture_reference(&scrn->tex, NULL);
- pipe_buffer_reference(&scrn->buffer, NULL);
+err_tex:
return EGL_FALSE;
}
diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h
index dd4730f957..f280748d65 100644
--- a/src/gallium/state_trackers/egl/egl_tracker.h
+++ b/src/gallium/state_trackers/egl/egl_tracker.h
@@ -94,7 +94,6 @@ struct drm_screen
* pipe
*/
- struct pipe_buffer *buffer;
struct pipe_texture *tex;
struct pipe_surface *surface;
diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
index 20d682de3f..b1683b891b 100644
--- a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
+++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
@@ -51,6 +51,7 @@ static int vlResizeFrameBuffer
struct vlBasicCSC *basic_csc;
struct pipe_context *pipe;
struct pipe_texture template;
+ float clear_color[4];
assert(csc);
@@ -68,7 +69,12 @@ static int vlResizeFrameBuffer
basic_csc->viewport.translate[1] = 0;
basic_csc->viewport.translate[2] = 0;
basic_csc->viewport.translate[3] = 0;
-
+
+ clear_color[0] = 0.0f;
+ clear_color[1] = 0.0f;
+ clear_color[2] = 0.0f;
+ clear_color[3] = 0.0f;
+
if (basic_csc->framebuffer_tex)
{
pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL);
@@ -98,7 +104,7 @@ static int vlResizeFrameBuffer
/* Clear to black, in case video doesn't fill the entire window */
pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer);
- pipe->clear(pipe, PIPE_CLEAR_COLOR, 0, 0.0f, 0);
+ pipe->clear(pipe, PIPE_CLEAR_COLOR, clear_color, 0.0f, 0);
return 0;
}
@@ -425,7 +431,7 @@ static int vlCreateVertexShader
*/
for (i = 0; i < 2; ++i)
{
- inst = vl_inst4(TGSI_OPCODE_MADD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1);
+ inst = vl_inst4(TGSI_OPCODE_MAD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
}
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc
index ef4a4b2add..34d93e1df0 100644
--- a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc
@@ -615,7 +615,7 @@ static int vlCreateFragmentShaderFieldPMB
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* floor t3, t3 ; Get rid of fractional part */
- inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+ inst = vl_inst2(TGSI_OPCODE_FLR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* mul t3, t3, c1.y ; Multiply by 2 */
@@ -632,7 +632,7 @@ static int vlCreateFragmentShaderFieldPMB
/* TODO: Move to conditional tex fetch on t3 instead of lerp */
/* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */
- inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* add o0, t0, t1 ; Add ref and differential to form final output */
@@ -969,7 +969,7 @@ static int vlCreateFragmentShaderFrameBMB
}
/* lerp t1, c1.x, t1, t2 ; Blend past and future texels */
- inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
@@ -1116,7 +1116,7 @@ static int vlCreateFragmentShaderFieldBMB
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* floor t3, t3 ; Get rid of fractional part */
- inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+ inst = vl_inst2(TGSI_OPCODE_FLR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* mul t3, t3, c1.y ; Multiply by 2 */
@@ -1143,7 +1143,7 @@ static int vlCreateFragmentShaderFieldBMB
/* TODO: Move to conditional tex fetch on t3 instead of lerp */
/* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */
- inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/*
@@ -1158,11 +1158,11 @@ static int vlCreateFragmentShaderFieldBMB
/* TODO: Move to conditional tex fetch on t3 instead of lerp */
/* lerp t2, t3, t4, t5 ; Choose between top and bottom fields based on Y % 2 */
- inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5);
+ inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/* lerp t1, c1.x, t1, t2 ; Blend past and future texels */
- inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c
index f0a4826a00..f0abd12e3d 100644
--- a/src/gallium/state_trackers/python/st_softpipe_winsys.c
+++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c
@@ -172,6 +172,7 @@ st_softpipe_surface_buffer_create(struct pipe_winsys *winsys,
unsigned width, unsigned height,
enum pipe_format format,
unsigned usage,
+ unsigned tex_usage,
unsigned *stride)
{
const unsigned alignment = 64;
diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript
index 69b88618ec..b05944a33b 100644
--- a/src/gallium/state_trackers/wgl/SConscript
+++ b/src/gallium/state_trackers/wgl/SConscript
@@ -18,20 +18,17 @@ if env['platform'] in ['windows']:
])
sources = [
- 'icd/stw_icd.c',
-
- 'wgl/stw_wgl.c',
-
- 'shared/stw_context.c',
- 'shared/stw_device.c',
- 'shared/stw_framebuffer.c',
- 'shared/stw_pixelformat.c',
- 'shared/stw_extensionsstring.c',
- 'shared/stw_extswapinterval.c',
- 'shared/stw_getprocaddress.c',
- 'shared/stw_extgallium.c',
- 'shared/stw_arbpixelformat.c',
- 'shared/stw_tls.c',
+ 'stw_context.c',
+ 'stw_device.c',
+ 'stw_ext_extensionsstring.c',
+ 'stw_ext_gallium.c',
+ 'stw_ext_pixelformat.c',
+ 'stw_ext_swapinterval.c',
+ 'stw_framebuffer.c',
+ 'stw_getprocaddress.c',
+ 'stw_pixelformat.c',
+ 'stw_tls.c',
+ 'stw_wgl.c',
]
wgl = env.ConvenienceLibrary(
diff --git a/src/gallium/state_trackers/wgl/opengl32.def b/src/gallium/state_trackers/wgl/opengl32.def
index 596417ed84..5daa6ddd41 100644
--- a/src/gallium/state_trackers/wgl/opengl32.def
+++ b/src/gallium/state_trackers/wgl/opengl32.def
@@ -376,6 +376,7 @@ EXPORTS
DrvDescribePixelFormat
DrvGetLayerPaletteEntries
DrvGetProcAddress
+ DrvPresentBuffers
DrvRealizeLayerPalette
DrvReleaseContext
DrvSetCallbackProcs
diff --git a/src/gallium/state_trackers/wgl/opengl32.mingw.def b/src/gallium/state_trackers/wgl/opengl32.mingw.def
index 1f03ea3b37..6ebb31a6f1 100644
--- a/src/gallium/state_trackers/wgl/opengl32.mingw.def
+++ b/src/gallium/state_trackers/wgl/opengl32.mingw.def
@@ -375,6 +375,7 @@ EXPORTS
DrvDescribePixelFormat = DrvDescribePixelFormat@16
DrvGetLayerPaletteEntries = DrvGetLayerPaletteEntries@20
DrvGetProcAddress = DrvGetProcAddress@4
+ DrvPresentBuffers = DrvPresentBuffers@8
DrvRealizeLayerPalette = DrvRealizeLayerPalette@12
DrvReleaseContext = DrvReleaseContext@4
DrvSetCallbackProcs = DrvSetCallbackProcs@8
diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c
deleted file mode 100644
index 4968ecc692..0000000000
--- a/src/gallium/state_trackers/wgl/shared/stw_context.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-#include <windows.h>
-
-#include "main/mtypes.h"
-#include "main/context.h"
-#include "pipe/p_compiler.h"
-#include "pipe/p_context.h"
-#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
-
-#ifdef DEBUG
-#include "trace/tr_screen.h"
-#include "trace/tr_context.h"
-#endif
-
-#include "shared/stw_device.h"
-#include "shared/stw_winsys.h"
-#include "shared/stw_framebuffer.h"
-#include "shared/stw_pixelformat.h"
-#include "stw_public.h"
-#include "stw_context.h"
-#include "stw_tls.h"
-
-
-static INLINE struct stw_context *
-stw_context(GLcontext *glctx)
-{
- if(!glctx)
- return NULL;
- assert(glctx->DriverCtx);
- return (struct stw_context *)glctx->DriverCtx;
-}
-
-static INLINE struct stw_context *
-stw_current_context(void)
-{
- /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT
- * might return the current context of the thread first seen. */
- _glapi_check_multithread();
-
- {
- GET_CURRENT_CONTEXT( glctx );
- return stw_context(glctx);
- }
-}
-
-BOOL
-stw_copy_context(
- UINT_PTR hglrcSrc,
- UINT_PTR hglrcDst,
- UINT mask )
-{
- struct stw_context *src;
- struct stw_context *dst;
- BOOL ret = FALSE;
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
-
- src = stw_lookup_context_locked( hglrcSrc );
- dst = stw_lookup_context_locked( hglrcDst );
-
- if (src && dst) {
- /* FIXME */
- assert(0);
- (void) src;
- (void) dst;
- (void) mask;
- }
-
- pipe_mutex_unlock( stw_dev->ctx_mutex );
-
- return ret;
-}
-
-BOOL
-stw_share_lists(
- UINT_PTR hglrc1,
- UINT_PTR hglrc2 )
-{
- struct stw_context *ctx1;
- struct stw_context *ctx2;
- BOOL ret = FALSE;
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
-
- ctx1 = stw_lookup_context_locked( hglrc1 );
- ctx2 = stw_lookup_context_locked( hglrc2 );
-
- if (ctx1 && ctx2 &&
- ctx1->iPixelFormat == ctx2->iPixelFormat) {
- ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
- }
-
- pipe_mutex_unlock( stw_dev->ctx_mutex );
-
- return ret;
-}
-
-static void
-stw_viewport(GLcontext * glctx, GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx;
- struct stw_framebuffer *fb;
-
- fb = stw_framebuffer_from_hdc( ctx->hdc );
- if(fb) {
- stw_framebuffer_update(fb);
- stw_framebuffer_release(fb);
- }
-}
-
-UINT_PTR
-stw_create_layer_context(
- HDC hdc,
- int iLayerPlane )
-{
- int iPixelFormat;
- const struct stw_pixelformat_info *pfi;
- GLvisual visual;
- struct stw_context *ctx = NULL;
- struct pipe_screen *screen = NULL;
- struct pipe_context *pipe = NULL;
-
- if(!stw_dev)
- return 0;
-
- if (iLayerPlane != 0)
- return 0;
-
- iPixelFormat = GetPixelFormat(hdc);
- if(!iPixelFormat)
- return 0;
-
- pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
- stw_pixelformat_visual(&visual, pfi);
-
- ctx = CALLOC_STRUCT( stw_context );
- if (ctx == NULL)
- goto no_ctx;
-
- ctx->hdc = hdc;
- ctx->iPixelFormat = iPixelFormat;
-
- screen = stw_dev->screen;
-
-#ifdef DEBUG
- /* Unwrap screen */
- if(stw_dev->trace_running)
- screen = trace_screen(screen)->screen;
-#endif
-
- pipe = stw_dev->stw_winsys->create_context( screen );
- if (pipe == NULL)
- goto no_pipe;
-
-#ifdef DEBUG
- /* Wrap context */
- if(stw_dev->trace_running)
- pipe = trace_context_create(stw_dev->screen, pipe);
-#endif
-
- /* pass to stw_flush_frontbuffer as context_private */
- assert(!pipe->priv);
- pipe->priv = hdc;
-
- ctx->st = st_create_context( pipe, &visual, NULL );
- if (ctx->st == NULL)
- goto no_st_ctx;
-
- ctx->st->ctx->DriverCtx = ctx;
- ctx->st->ctx->Driver.Viewport = stw_viewport;
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
- ctx->hglrc = handle_table_add(stw_dev->ctx_table, ctx);
- pipe_mutex_unlock( stw_dev->ctx_mutex );
- if (!ctx->hglrc)
- goto no_hglrc;
-
- return ctx->hglrc;
-
-no_hglrc:
- st_destroy_context(ctx->st);
- goto no_pipe; /* st_context_destroy already destroys pipe */
-no_st_ctx:
- pipe->destroy( pipe );
-no_pipe:
- FREE(ctx);
-no_ctx:
- return 0;
-}
-
-BOOL
-stw_delete_context(
- UINT_PTR hglrc )
-{
- struct stw_context *ctx ;
- BOOL ret = FALSE;
-
- if (!stw_dev)
- return FALSE;
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
- ctx = stw_lookup_context_locked(hglrc);
- handle_table_remove(stw_dev->ctx_table, hglrc);
- pipe_mutex_unlock( stw_dev->ctx_mutex );
-
- if (ctx) {
- struct stw_context *curctx = stw_current_context();
-
- /* Unbind current if deleting current context. */
- if (curctx == ctx)
- st_make_current( NULL, NULL, NULL );
-
- st_destroy_context(ctx->st);
- FREE(ctx);
-
- ret = TRUE;
- }
-
- return ret;
-}
-
-BOOL
-stw_release_context(
- UINT_PTR hglrc )
-{
- struct stw_context *ctx;
-
- if (!stw_dev)
- return FALSE;
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
- ctx = stw_lookup_context_locked( hglrc );
- pipe_mutex_unlock( stw_dev->ctx_mutex );
-
- if (!ctx)
- return FALSE;
-
- /* The expectation is that ctx is the same context which is
- * current for this thread. We should check that and return False
- * if not the case.
- */
- if (ctx != stw_current_context())
- return FALSE;
-
- if (stw_make_current( NULL, 0 ) == FALSE)
- return FALSE;
-
- return TRUE;
-}
-
-
-UINT_PTR
-stw_get_current_context( void )
-{
- struct stw_context *ctx;
-
- ctx = stw_current_context();
- if(!ctx)
- return 0;
-
- return ctx->hglrc;
-}
-
-HDC
-stw_get_current_dc( void )
-{
- struct stw_context *ctx;
-
- ctx = stw_current_context();
- if(!ctx)
- return NULL;
-
- return ctx->hdc;
-}
-
-BOOL
-stw_make_current(
- HDC hdc,
- UINT_PTR hglrc )
-{
- struct stw_context *curctx = NULL;
- struct stw_context *ctx = NULL;
- struct stw_framebuffer *fb = NULL;
-
- if (!stw_dev)
- goto fail;
-
- curctx = stw_current_context();
- if (curctx != NULL) {
- if (curctx->hglrc != hglrc)
- st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
- /* Return if already current. */
- if (curctx->hglrc == hglrc && curctx->hdc == hdc) {
- ctx = curctx;
- fb = stw_framebuffer_from_hdc( hdc );
- goto success;
- }
- }
-
- if (hdc == NULL || hglrc == 0) {
- return st_make_current( NULL, NULL, NULL );
- }
-
- pipe_mutex_lock( stw_dev->ctx_mutex );
- ctx = stw_lookup_context_locked( hglrc );
- pipe_mutex_unlock( stw_dev->ctx_mutex );
- if(!ctx)
- goto fail;
-
- fb = stw_framebuffer_from_hdc( hdc );
- if(!fb) {
- /* Applications should call SetPixelFormat before creating a context,
- * but not all do, and the opengl32 runtime seems to use a default pixel
- * format in some cases, so we must create a framebuffer for those here
- */
- int iPixelFormat = GetPixelFormat(hdc);
- if(iPixelFormat)
- fb = stw_framebuffer_create( hdc, iPixelFormat );
- if(!fb)
- goto fail;
- }
-
- if(fb->iPixelFormat != ctx->iPixelFormat)
- goto fail;
-
- /* Lazy allocation of the frame buffer */
- if(!stw_framebuffer_allocate(fb))
- goto fail;
-
- /* Bind the new framebuffer */
- ctx->hdc = hdc;
-
- /* pass to stw_flush_frontbuffer as context_private */
- ctx->st->pipe->priv = hdc;
-
- if(!st_make_current( ctx->st, fb->stfb, fb->stfb ))
- goto fail;
-
-success:
- assert(fb);
- if(fb) {
- stw_framebuffer_update(fb);
- stw_framebuffer_release(fb);
- }
-
- return TRUE;
-
-fail:
- if(fb)
- stw_framebuffer_release(fb);
- st_make_current( NULL, NULL, NULL );
- return FALSE;
-}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_public.h b/src/gallium/state_trackers/wgl/shared/stw_public.h
deleted file mode 100644
index 7fe9cfb356..0000000000
--- a/src/gallium/state_trackers/wgl/shared/stw_public.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**************************************************************************
- *
- * 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 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 STW_PUBLIC_H
-#define STW_PUBLIC_H
-
-#include <windows.h>
-
-BOOL stw_copy_context( UINT_PTR hglrcSrc,
- UINT_PTR hglrcDst,
- UINT mask );
-
-UINT_PTR stw_create_layer_context( HDC hdc,
- int iLayerPlane );
-
-BOOL stw_share_lists( UINT_PTR hglrc1, UINT_PTR hglrc2 );
-
-BOOL stw_delete_context( UINT_PTR hglrc );
-
-BOOL
-stw_release_context( UINT_PTR dhglrc );
-
-UINT_PTR stw_get_current_context( void );
-
-HDC stw_get_current_dc( void );
-
-BOOL stw_make_current( HDC hdc, UINT_PTR hglrc );
-
-BOOL stw_swap_buffers( HDC hdc );
-
-BOOL
-stw_swap_layer_buffers( HDC hdc, UINT fuPlanes );
-
-PROC stw_get_proc_address( LPCSTR lpszProc );
-
-int stw_pixelformat_describe( HDC hdc,
- int iPixelFormat,
- UINT nBytes,
- LPPIXELFORMATDESCRIPTOR ppfd );
-
-int stw_pixelformat_get( HDC hdc );
-
-BOOL stw_pixelformat_set( HDC hdc,
- int iPixelFormat );
-
-int stw_pixelformat_choose( HDC hdc,
- CONST PIXELFORMATDESCRIPTOR *ppfd );
-
-#endif
diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.c b/src/gallium/state_trackers/wgl/stw_context.c
index 347f40aa06..f2f0264844 100644
--- a/src/gallium/state_trackers/wgl/icd/stw_icd.c
+++ b/src/gallium/state_trackers/wgl/stw_context.c
@@ -26,18 +26,49 @@
**************************************************************************/
#include <windows.h>
-#include <stdio.h>
-#include "GL/gl.h"
-
-#include "util/u_debug.h"
-#include "pipe/p_thread.h"
-
-#include "shared/stw_public.h"
-#include "icd/stw_icd.h"
+#include "main/mtypes.h"
+#include "main/context.h"
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_public.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#endif
+
+#include "stw_icd.h"
+#include "stw_device.h"
+#include "stw_winsys.h"
+#include "stw_framebuffer.h"
+#include "stw_pixelformat.h"
+#include "stw_context.h"
+#include "stw_tls.h"
+
+
+static INLINE struct stw_context *
+stw_context(GLcontext *glctx)
+{
+ if(!glctx)
+ return NULL;
+ assert(glctx->DriverCtx);
+ return (struct stw_context *)glctx->DriverCtx;
+}
-#define DBG 0
+static INLINE struct stw_context *
+stw_current_context(void)
+{
+ /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT
+ * might return the current context of the thread first seen. */
+ _glapi_check_multithread();
+ {
+ GET_CURRENT_CONTEXT( glctx );
+ return stw_context(glctx);
+ }
+}
BOOL APIENTRY
DrvCopyContext(
@@ -45,24 +76,64 @@ DrvCopyContext(
DHGLRC dhrcDest,
UINT fuMask )
{
- return stw_copy_context(dhrcSource, dhrcDest, fuMask);
-}
+ struct stw_context *src;
+ struct stw_context *dst;
+ BOOL ret = FALSE;
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+
+ src = stw_lookup_context_locked( dhrcSource );
+ dst = stw_lookup_context_locked( dhrcDest );
+
+ if (src && dst) {
+ /* FIXME */
+ assert(0);
+ (void) src;
+ (void) dst;
+ (void) fuMask;
+ }
-DHGLRC APIENTRY
-DrvCreateLayerContext(
- HDC hdc,
- INT iLayerPlane )
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ return ret;
+}
+
+BOOL APIENTRY
+DrvShareLists(
+ DHGLRC dhglrc1,
+ DHGLRC dhglrc2 )
{
- DHGLRC r;
+ struct stw_context *ctx1;
+ struct stw_context *ctx2;
+ BOOL ret = FALSE;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
- r = stw_create_layer_context( hdc, iLayerPlane );
+ ctx1 = stw_lookup_context_locked( dhglrc1 );
+ ctx2 = stw_lookup_context_locked( dhglrc2 );
+
+ if (ctx1 && ctx2 &&
+ ctx1->iPixelFormat == ctx2->iPixelFormat) {
+ ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
+ }
+
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
- if (DBG)
- debug_printf( "%s( %p, %i ) = %u\n",
- __FUNCTION__, hdc, iLayerPlane, r );
+ return ret;
+}
+
+static void
+stw_viewport(GLcontext * glctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx;
+ struct stw_framebuffer *fb;
- return r;
+ fb = stw_framebuffer_from_hdc( ctx->hdc );
+ if(fb) {
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+ }
}
DHGLRC APIENTRY
@@ -72,114 +143,253 @@ DrvCreateContext(
return DrvCreateLayerContext( hdc, 0 );
}
-BOOL APIENTRY
-DrvDeleteContext(
- DHGLRC dhglrc )
+DHGLRC APIENTRY
+DrvCreateLayerContext(
+ HDC hdc,
+ INT iLayerPlane )
{
- BOOL r;
+ int iPixelFormat;
+ const struct stw_pixelformat_info *pfi;
+ GLvisual visual;
+ struct stw_context *ctx = NULL;
+ struct pipe_screen *screen = NULL;
+ struct pipe_context *pipe = NULL;
- r = stw_delete_context( dhglrc );
+ if(!stw_dev)
+ return 0;
- if (DBG)
- debug_printf( "%s( %u ) = %u\n",
- __FUNCTION__, dhglrc, r );
+ if (iLayerPlane != 0)
+ return 0;
+
+ iPixelFormat = GetPixelFormat(hdc);
+ if(!iPixelFormat)
+ return 0;
- return r;
+ pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
+ stw_pixelformat_visual(&visual, pfi);
+
+ ctx = CALLOC_STRUCT( stw_context );
+ if (ctx == NULL)
+ goto no_ctx;
+
+ ctx->hdc = hdc;
+ ctx->iPixelFormat = iPixelFormat;
+
+ screen = stw_dev->screen;
+
+#ifdef DEBUG
+ /* Unwrap screen */
+ if(stw_dev->trace_running)
+ screen = trace_screen(screen)->screen;
+#endif
+
+ pipe = stw_dev->stw_winsys->create_context( screen );
+ if (pipe == NULL)
+ goto no_pipe;
+
+#ifdef DEBUG
+ /* Wrap context */
+ if(stw_dev->trace_running)
+ pipe = trace_context_create(stw_dev->screen, pipe);
+#endif
+
+ /* pass to stw_flush_frontbuffer as context_private */
+ assert(!pipe->priv);
+ pipe->priv = hdc;
+
+ ctx->st = st_create_context( pipe, &visual, NULL );
+ if (ctx->st == NULL)
+ goto no_st_ctx;
+
+ ctx->st->ctx->DriverCtx = ctx;
+ ctx->st->ctx->Driver.Viewport = stw_viewport;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+ if (!ctx->dhglrc)
+ goto no_hglrc;
+
+ return ctx->dhglrc;
+
+no_hglrc:
+ st_destroy_context(ctx->st);
+ goto no_pipe; /* st_context_destroy already destroys pipe */
+no_st_ctx:
+ pipe->destroy( pipe );
+no_pipe:
+ FREE(ctx);
+no_ctx:
+ return 0;
}
BOOL APIENTRY
-DrvDescribeLayerPlane(
- HDC hdc,
- INT iPixelFormat,
- INT iLayerPlane,
- UINT nBytes,
- LPLAYERPLANEDESCRIPTOR plpd )
+DrvDeleteContext(
+ DHGLRC dhglrc )
{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
+ struct stw_context *ctx ;
+ BOOL ret = FALSE;
+
+ if (!stw_dev)
+ return FALSE;
- return FALSE;
-}
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked(dhglrc);
+ handle_table_remove(stw_dev->ctx_table, dhglrc);
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
-LONG APIENTRY
-DrvDescribePixelFormat(
- HDC hdc,
- INT iPixelFormat,
- ULONG cjpfd,
- PIXELFORMATDESCRIPTOR *ppfd )
-{
- LONG r;
+ if (ctx) {
+ struct stw_context *curctx = stw_current_context();
+
+ /* Unbind current if deleting current context. */
+ if (curctx == ctx)
+ st_make_current( NULL, NULL, NULL );
- r = stw_pixelformat_describe( hdc, iPixelFormat, cjpfd, ppfd );
+ st_destroy_context(ctx->st);
+ FREE(ctx);
- if (DBG)
- debug_printf( "%s( %p, %d, %u, %p ) = %d\n",
- __FUNCTION__, hdc, iPixelFormat, cjpfd, ppfd, r );
+ ret = TRUE;
+ }
- return r;
+ return ret;
}
-int APIENTRY
-DrvGetLayerPaletteEntries(
- HDC hdc,
- INT iLayerPlane,
- INT iStart,
- INT cEntries,
- COLORREF *pcr )
+BOOL APIENTRY
+DrvReleaseContext(
+ DHGLRC dhglrc )
{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
+ struct stw_context *ctx;
- return 0;
-}
+ if (!stw_dev)
+ return FALSE;
-PROC APIENTRY
-DrvGetProcAddress(
- LPCSTR lpszProc )
-{
- PROC r;
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked( dhglrc );
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
- r = stw_get_proc_address( lpszProc );
+ if (!ctx)
+ return FALSE;
+
+ /* The expectation is that ctx is the same context which is
+ * current for this thread. We should check that and return False
+ * if not the case.
+ */
+ if (ctx != stw_current_context())
+ return FALSE;
- if (DBG)
- debug_printf( "%s( \"%s\" ) = %p\n", __FUNCTION__, lpszProc, r );
+ if (stw_make_current( NULL, 0 ) == FALSE)
+ return FALSE;
- return r;
+ return TRUE;
}
-BOOL APIENTRY
-DrvRealizeLayerPalette(
- HDC hdc,
- INT iLayerPlane,
- BOOL bRealize )
+
+DHGLRC
+stw_get_current_context( void )
{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
+ struct stw_context *ctx;
- return FALSE;
+ ctx = stw_current_context();
+ if(!ctx)
+ return 0;
+
+ return ctx->dhglrc;
}
-BOOL APIENTRY
-DrvReleaseContext(
- DHGLRC dhglrc )
+HDC
+stw_get_current_dc( void )
{
- return stw_release_context(dhglrc);
+ struct stw_context *ctx;
+
+ ctx = stw_current_context();
+ if(!ctx)
+ return NULL;
+
+ return ctx->hdc;
}
-void APIENTRY
-DrvSetCallbackProcs(
- INT nProcs,
- PROC *pProcs )
+BOOL
+stw_make_current(
+ HDC hdc,
+ DHGLRC dhglrc )
{
- if (DBG)
- debug_printf( "%s( %d, %p )\n", __FUNCTION__, nProcs, pProcs );
+ struct stw_context *curctx = NULL;
+ struct stw_context *ctx = NULL;
+ struct stw_framebuffer *fb = NULL;
- return;
-}
+ if (!stw_dev)
+ goto fail;
+
+ curctx = stw_current_context();
+ if (curctx != NULL) {
+ if (curctx->dhglrc != dhglrc)
+ st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* Return if already current. */
+ if (curctx->dhglrc == dhglrc && curctx->hdc == hdc) {
+ ctx = curctx;
+ fb = stw_framebuffer_from_hdc( hdc );
+ goto success;
+ }
+ }
+
+ if (hdc == NULL || dhglrc == 0) {
+ return st_make_current( NULL, NULL, NULL );
+ }
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked( dhglrc );
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+ if(!ctx)
+ goto fail;
+
+ fb = stw_framebuffer_from_hdc( hdc );
+ if(!fb) {
+ /* Applications should call SetPixelFormat before creating a context,
+ * but not all do, and the opengl32 runtime seems to use a default pixel
+ * format in some cases, so we must create a framebuffer for those here
+ */
+ int iPixelFormat = GetPixelFormat(hdc);
+ if(iPixelFormat)
+ fb = stw_framebuffer_create( hdc, iPixelFormat );
+ if(!fb)
+ goto fail;
+ }
+
+ if(fb->iPixelFormat != ctx->iPixelFormat)
+ goto fail;
+
+ /* Lazy allocation of the frame buffer */
+ if(!stw_framebuffer_allocate(fb))
+ goto fail;
+
+ /* Bind the new framebuffer */
+ ctx->hdc = hdc;
+
+ /* pass to stw_flush_frontbuffer as context_private */
+ ctx->st->pipe->priv = hdc;
+
+ if(!st_make_current( ctx->st, fb->stfb, fb->stfb ))
+ goto fail;
+
+success:
+ assert(fb);
+ if(fb) {
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+ }
+
+ return TRUE;
+fail:
+ if(fb)
+ stw_framebuffer_release(fb);
+ st_make_current( NULL, NULL, NULL );
+ return FALSE;
+}
/**
- * Although WGL allows different dispatch entrypoints per context
+ * Although WGL allows different dispatch entrypoints per context
*/
static const GLCLTPROCTABLE cpt =
{
@@ -524,7 +734,6 @@ static const GLCLTPROCTABLE cpt =
}
};
-
PGLCLTPROCTABLE APIENTRY
DrvSetContext(
HDC hdc,
@@ -532,86 +741,9 @@ DrvSetContext(
PFN_SETPROCTABLE pfnSetProcTable )
{
PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
-
+
if (!stw_make_current( hdc, dhglrc ))
r = NULL;
-
- if (DBG)
- debug_printf( "%s( 0x%p, %u, 0x%p ) = %p\n",
- __FUNCTION__, hdc, dhglrc, pfnSetProcTable, r );
-
- return r;
-}
-
-int APIENTRY
-DrvSetLayerPaletteEntries(
- HDC hdc,
- INT iLayerPlane,
- INT iStart,
- INT cEntries,
- CONST COLORREF *pcr )
-{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
-
- return 0;
-}
-
-BOOL APIENTRY
-DrvSetPixelFormat(
- HDC hdc,
- LONG iPixelFormat )
-{
- BOOL r;
-
- r = stw_pixelformat_set( hdc, iPixelFormat );
-
- if (DBG)
- debug_printf( "%s( %p, %d ) = %s\n", __FUNCTION__, hdc, iPixelFormat, r ? "TRUE" : "FALSE" );
return r;
}
-
-BOOL APIENTRY
-DrvShareLists(
- DHGLRC dhglrc1,
- DHGLRC dhglrc2 )
-{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
-
- return stw_share_lists(dhglrc1, dhglrc2);
-}
-
-BOOL APIENTRY
-DrvSwapBuffers(
- HDC hdc )
-{
- if (DBG)
- debug_printf( "%s( %p )\n", __FUNCTION__, hdc );
-
- return stw_swap_buffers( hdc );
-}
-
-BOOL APIENTRY
-DrvSwapLayerBuffers(
- HDC hdc,
- UINT fuPlanes )
-{
- if (DBG)
- debug_printf( "%s\n", __FUNCTION__ );
-
- return stw_swap_layer_buffers( hdc, fuPlanes );
-}
-
-BOOL APIENTRY
-DrvValidateVersion(
- ULONG ulVersion )
-{
- if (DBG)
- debug_printf( "%s( %u )\n", __FUNCTION__, ulVersion );
-
- /* TODO: get the expected version from the winsys */
-
- return ulVersion == 1;
-}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.h b/src/gallium/state_trackers/wgl/stw_context.h
index 166471de5e..256c27e21e 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_context.h
+++ b/src/gallium/state_trackers/wgl/stw_context.h
@@ -35,9 +35,15 @@ struct st_context;
struct stw_context
{
struct st_context *st;
- UINT_PTR hglrc;
+ DHGLRC dhglrc;
int iPixelFormat;
HDC hdc;
};
+DHGLRC stw_get_current_context( void );
+
+HDC stw_get_current_dc( void );
+
+BOOL stw_make_current( HDC hdc, DHGLRC dhglrc );
+
#endif /* STW_CONTEXT_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c
index 0b6954915a..985b8f0456 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_device.c
+++ b/src/gallium/state_trackers/wgl/stw_device.c
@@ -29,6 +29,7 @@
#include "glapi/glthread.h"
#include "util/u_debug.h"
+#include "util/u_math.h"
#include "pipe/p_screen.h"
#include "state_tracker/st_public.h"
@@ -37,12 +38,12 @@
#include "trace/tr_texture.h"
#endif
-#include "shared/stw_device.h"
-#include "shared/stw_winsys.h"
-#include "shared/stw_pixelformat.h"
-#include "shared/stw_public.h"
-#include "shared/stw_tls.h"
-#include "shared/stw_framebuffer.h"
+#include "stw_device.h"
+#include "stw_winsys.h"
+#include "stw_pixelformat.h"
+#include "stw_icd.h"
+#include "stw_tls.h"
+#include "stw_framebuffer.h"
#ifdef WIN32_THREADS
extern _glthread_Mutex OneTimeLock;
@@ -62,38 +63,28 @@ stw_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surface,
void *context_private )
{
- const struct stw_winsys *stw_winsys = stw_dev->stw_winsys;
HDC hdc = (HDC)context_private;
struct stw_framebuffer *fb;
fb = stw_framebuffer_from_hdc( hdc );
- /* fb can be NULL if window was destroyed already */
- if (fb) {
+ if (!fb) {
+ /* fb can be NULL if window was destroyed already */
+ return;
+ }
+
#if DEBUG
- {
- struct pipe_surface *surface2;
-
- if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_FRONT_LEFT, &surface2 ))
- assert(0);
- else
- assert(surface2 == surface);
- }
-#endif
+ {
+ /* ensure that a random surface was not passed to us */
+ struct pipe_surface *surface2;
-#ifdef DEBUG
- if(stw_dev->trace_running) {
- screen = trace_screen(screen)->screen;
- surface = trace_surface(surface)->surface;
- }
-#endif
- }
-
- stw_winsys->flush_frontbuffer(screen, surface, hdc);
-
- if(fb) {
- stw_framebuffer_update(fb);
- stw_framebuffer_release(fb);
+ if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_FRONT_LEFT, &surface2 ))
+ assert(0);
+ else
+ assert(surface2 == surface);
}
+#endif
+
+ stw_framebuffer_present_locked(hdc, fb, ST_SURFACE_FRONT_LEFT);
}
@@ -126,6 +117,9 @@ stw_init(const struct stw_winsys *stw_winsys)
if(!screen)
goto error1;
+ if(stw_winsys->get_adapter_luid)
+ stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid);
+
#ifdef DEBUG
stw_dev->screen = trace_screen_create(screen);
stw_dev->trace_running = stw_dev->screen != screen ? TRUE : FALSE;
@@ -182,7 +176,7 @@ stw_cleanup(void)
/* Ensure all contexts are destroyed */
i = handle_table_get_first_handle(stw_dev->ctx_table);
while (i) {
- stw_delete_context(i);
+ DrvDeleteContext(i);
i = handle_table_get_next_handle(stw_dev->ctx_table, i);
}
handle_table_destroy(stw_dev->ctx_table);
@@ -212,7 +206,7 @@ stw_cleanup(void)
struct stw_context *
-stw_lookup_context_locked( UINT_PTR dhglrc )
+stw_lookup_context_locked( DHGLRC dhglrc )
{
if (dhglrc == 0)
return NULL;
@@ -223,3 +217,28 @@ stw_lookup_context_locked( UINT_PTR dhglrc )
return (struct stw_context *) handle_table_get(stw_dev->ctx_table, dhglrc);
}
+
+void APIENTRY
+DrvSetCallbackProcs(
+ INT nProcs,
+ PROC *pProcs )
+{
+ size_t size;
+
+ if (stw_dev == NULL)
+ return;
+
+ size = MIN2(nProcs * sizeof *pProcs, sizeof stw_dev->callbacks);
+ memcpy(&stw_dev->callbacks, pProcs, size);
+
+ return;
+}
+
+
+BOOL APIENTRY
+DrvValidateVersion(
+ ULONG ulVersion )
+{
+ /* TODO: get the expected version from the winsys */
+ return ulVersion == 1;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.h b/src/gallium/state_trackers/wgl/stw_device.h
index e1bb9518dd..0bf3b0da82 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_device.h
+++ b/src/gallium/state_trackers/wgl/stw_device.h
@@ -29,11 +29,10 @@
#define STW_DEVICE_H_
-#include <windows.h>
-
#include "pipe/p_compiler.h"
#include "pipe/p_thread.h"
#include "util/u_handle_table.h"
+#include "stw_icd.h"
#include "stw_pixelformat.h"
@@ -53,10 +52,14 @@ struct stw_device
boolean trace_running;
#endif
+ LUID AdapterLuid;
+
struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS];
unsigned pixelformat_count;
unsigned pixelformat_extended_count;
+ GLCALLBACKTABLE callbacks;
+
pipe_mutex ctx_mutex;
struct handle_table *ctx_table;
@@ -69,7 +72,7 @@ struct stw_device
};
struct stw_context *
-stw_lookup_context_locked( UINT_PTR hglrc );
+stw_lookup_context_locked( DHGLRC hglrc );
extern struct stw_device *stw_dev;
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
index 62c859e1f9..62c859e1f9 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extgallium.c b/src/gallium/state_trackers/wgl/stw_ext_gallium.c
index fc22737d7e..fb30ec5dba 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_extgallium.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_gallium.c
@@ -27,9 +27,9 @@
#include "pipe/p_screen.h"
-#include "stw_public.h"
#include "stw_device.h"
#include "stw_winsys.h"
+#include "stw_ext_gallium.h"
#ifdef DEBUG
#include "trace/tr_screen.h"
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extgallium.h b/src/gallium/state_trackers/wgl/stw_ext_gallium.h
index cc35f2bb7f..cc35f2bb7f 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_extgallium.h
+++ b/src/gallium/state_trackers/wgl/stw_ext_gallium.h
diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c
index 0e2d407699..8a9995aba8 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c
@@ -43,7 +43,6 @@
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
-#include "stw_public.h"
#include "stw_pixelformat.h"
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c b/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c
index 9eac6a1d09..9eac6a1d09 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c
diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c
index b8956bb550..8a3e11b6b4 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
+++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c
@@ -1,8 +1,8 @@
/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ *
+ * Copyright 2008-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
@@ -10,19 +10,19 @@
* 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
+ * 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 <windows.h>
@@ -38,9 +38,9 @@
#include "trace/tr_texture.h"
#endif
+#include "stw_icd.h"
#include "stw_framebuffer.h"
#include "stw_device.h"
-#include "stw_public.h"
#include "stw_winsys.h"
#include "stw_tls.h"
@@ -83,6 +83,9 @@ stw_framebuffer_destroy_locked(
*link = fb->next;
fb->next = NULL;
+ if(fb->shared_surface)
+ stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, fb->shared_surface);
+
st_unreference_framebuffer(fb->stfb);
pipe_mutex_unlock( fb->mutex );
@@ -106,13 +109,18 @@ static INLINE void
stw_framebuffer_get_size( struct stw_framebuffer *fb )
{
unsigned width, height;
- RECT rect;
+ RECT client_rect;
+ RECT window_rect;
+ POINT client_pos;
assert(fb->hWnd);
- GetClientRect( fb->hWnd, &rect );
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
+ /* Get the client area size. */
+ GetClientRect( fb->hWnd, &client_rect );
+ assert(client_rect.left == 0);
+ assert(client_rect.top == 0);
+ width = client_rect.right - client_rect.left;
+ height = client_rect.bottom - client_rect.top;
if(width < 1)
width = 1;
@@ -124,6 +132,31 @@ stw_framebuffer_get_size( struct stw_framebuffer *fb )
fb->width = width;
fb->height = height;
}
+
+ client_pos.x = 0;
+ client_pos.y = 0;
+ ClientToScreen(fb->hWnd, &client_pos);
+
+ GetWindowRect(fb->hWnd, &window_rect);
+
+ fb->client_rect.left = client_pos.x - window_rect.left;
+ fb->client_rect.top = client_pos.y - window_rect.top;
+ fb->client_rect.right = fb->client_rect.left + fb->width;
+ fb->client_rect.bottom = fb->client_rect.top + fb->height;
+
+#if 0
+ debug_printf("\n");
+ debug_printf("%s: client_position = (%i, %i)\n",
+ __FUNCTION__, client_pos.x, client_pos.y);
+ debug_printf("%s: window_rect = (%i, %i) - (%i, %i)\n",
+ __FUNCTION__,
+ window_rect.left, window_rect.top,
+ window_rect.right, window_rect.bottom);
+ debug_printf("%s: client_rect = (%i, %i) - (%i, %i)\n",
+ __FUNCTION__,
+ fb->client_rect.left, fb->client_rect.top,
+ fb->client_rect.right, fb->client_rect.bottom);
+#endif
}
@@ -155,6 +188,7 @@ stw_call_window_proc(
* can be masked out by the application. */
LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
if((lpWindowPos->flags & SWP_SHOWWINDOW) ||
+ !(lpWindowPos->flags & SWP_NOMOVE) ||
!(lpWindowPos->flags & SWP_NOSIZE)) {
fb = stw_framebuffer_from_hwnd( pParams->hwnd );
if(fb) {
@@ -379,10 +413,10 @@ stw_framebuffer_from_hwnd(
}
-BOOL
-stw_pixelformat_set(
+BOOL APIENTRY
+DrvSetPixelFormat(
HDC hdc,
- int iPixelFormat )
+ LONG iPixelFormat )
{
uint count;
uint index;
@@ -435,35 +469,24 @@ stw_pixelformat_get(
}
-BOOL
-stw_swap_buffers(
- HDC hdc )
+BOOL APIENTRY
+DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data)
{
struct stw_framebuffer *fb;
struct pipe_screen *screen;
struct pipe_surface *surface;
+ unsigned surface_index;
+ BOOL ret = FALSE;
fb = stw_framebuffer_from_hdc( hdc );
if (fb == NULL)
return FALSE;
- if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) {
- stw_framebuffer_release(fb);
- return TRUE;
- }
-
- /* If we're swapping the buffer associated with the current context
- * we have to flush any pending rendering commands first.
- */
- st_notify_swapbuffers( fb->stfb );
-
screen = stw_dev->screen;
-
- if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface )) {
- /* FIXME: this shouldn't happen, but does on glean */
- stw_framebuffer_release(fb);
- return FALSE;
- }
+
+ surface_index = (unsigned)(uintptr_t)data->pPrivateData;
+ if(!st_get_framebuffer_surface( fb->stfb, surface_index, &surface ))
+ goto fail;
#ifdef DEBUG
if(stw_dev->trace_running) {
@@ -472,22 +495,127 @@ stw_swap_buffers(
}
#endif
- stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
-
+ if(data->hSharedSurface != fb->hSharedSurface) {
+ if(fb->shared_surface) {
+ stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface);
+ fb->shared_surface = NULL;
+ }
+
+ fb->hSharedSurface = data->hSharedSurface;
+
+ if(data->hSharedSurface &&
+ stw_dev->stw_winsys->shared_surface_open) {
+ fb->shared_surface = stw_dev->stw_winsys->shared_surface_open(screen, fb->hSharedSurface);
+ }
+ }
+
+ if(fb->shared_surface) {
+ stw_dev->stw_winsys->compose(screen,
+ surface,
+ fb->shared_surface,
+ &fb->client_rect,
+ data->PresentHistoryToken);
+ }
+ else {
+ stw_dev->stw_winsys->present( screen, surface, hdc );
+ }
+
+ ret = TRUE;
+
+fail:
+
stw_framebuffer_update(fb);
+
stw_framebuffer_release(fb);
-
- return TRUE;
+
+ return ret;
}
+/**
+ * Queue a composition.
+ *
+ * It will drop the lock on success.
+ */
BOOL
-stw_swap_layer_buffers(
+stw_framebuffer_present_locked(HDC hdc,
+ struct stw_framebuffer *fb,
+ unsigned surface_index)
+{
+ if(stw_dev->callbacks.wglCbPresentBuffers &&
+ stw_dev->stw_winsys->compose) {
+ GLCBPRESENTBUFFERSDATA data;
+
+ memset(&data, 0, sizeof data);
+ data.magic1 = 2;
+ data.magic2 = 0;
+ data.AdapterLuid = stw_dev->AdapterLuid;
+ data.rect = fb->client_rect;
+ data.pPrivateData = (void *)(uintptr_t)surface_index;
+
+ stw_framebuffer_release(fb);
+
+ return stw_dev->callbacks.wglCbPresentBuffers(hdc, &data);
+ }
+ else {
+ struct pipe_screen *screen = stw_dev->screen;
+ struct pipe_surface *surface;
+
+ if(!st_get_framebuffer_surface( fb->stfb, surface_index, &surface )) {
+ /* FIXME: this shouldn't happen, but does on glean */
+ stw_framebuffer_release(fb);
+ return FALSE;
+ }
+
+#ifdef DEBUG
+ if(stw_dev->trace_running) {
+ screen = trace_screen(screen)->screen;
+ surface = trace_surface(surface)->surface;
+ }
+#endif
+
+ stw_dev->stw_winsys->present( screen, surface, hdc );
+
+ stw_framebuffer_update(fb);
+
+ stw_framebuffer_release(fb);
+
+ return TRUE;
+ }
+}
+
+
+BOOL APIENTRY
+DrvSwapBuffers(
+ HDC hdc )
+{
+ struct stw_framebuffer *fb;
+
+ fb = stw_framebuffer_from_hdc( hdc );
+ if (fb == NULL)
+ return FALSE;
+
+ if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) {
+ stw_framebuffer_release(fb);
+ return TRUE;
+ }
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ st_notify_swapbuffers( fb->stfb );
+
+ return stw_framebuffer_present_locked(hdc, fb, ST_SURFACE_BACK_LEFT);
+}
+
+
+BOOL APIENTRY
+DrvSwapLayerBuffers(
HDC hdc,
UINT fuPlanes )
{
if(fuPlanes & WGL_SWAP_MAIN_PLANE)
- return stw_swap_buffers(hdc);
+ return DrvSwapBuffers(hdc);
return FALSE;
}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h
index 13d29f37e4..5afbe74908 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h
+++ b/src/gallium/state_trackers/wgl/stw_framebuffer.h
@@ -73,9 +73,20 @@ struct stw_framebuffer
/* FIXME: Make this work for multiple contexts bound to the same framebuffer */
boolean must_resize;
+
unsigned width;
unsigned height;
+ /**
+ * Client area rectangle, relative to the window upper-left corner.
+ *
+ * @sa GLCBPRESENTBUFFERSDATA::rect.
+ */
+ RECT client_rect;
+
+ HANDLE hSharedSurface;
+ struct stw_shared_surface *shared_surface;
+
/**
* This is protected by stw_device::fb_mutex, not the mutex above.
*
@@ -126,6 +137,11 @@ BOOL
stw_framebuffer_allocate(
struct stw_framebuffer *fb );
+BOOL
+stw_framebuffer_present_locked(HDC hdc,
+ struct stw_framebuffer *fb,
+ unsigned surface_index);
+
void
stw_framebuffer_update(
struct stw_framebuffer *fb);
diff --git a/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/stw_getprocaddress.c
index 879ced925a..8875dc22f3 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c
+++ b/src/gallium/state_trackers/wgl/stw_getprocaddress.c
@@ -33,8 +33,7 @@
#include <GL/wglext.h>
#include "glapi/glapi.h"
-#include "stw_public.h"
-#include "stw_extgallium.h"
+#include "stw_ext_gallium.h"
struct stw_extension_entry
{
@@ -68,8 +67,8 @@ static const struct stw_extension_entry stw_extension_entries[] = {
{ NULL, NULL }
};
-PROC
-stw_get_proc_address(
+PROC APIENTRY
+DrvGetProcAddress(
LPCSTR lpszProc )
{
const struct stw_extension_entry *entry;
diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.h b/src/gallium/state_trackers/wgl/stw_icd.h
index cbc1a66548..02eb543fef 100644
--- a/src/gallium/state_trackers/wgl/icd/stw_icd.h
+++ b/src/gallium/state_trackers/wgl/stw_icd.h
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008-2009 Vmware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
* 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
+ * 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.
@@ -388,6 +388,113 @@ typedef struct _GLCLTPROCTABLE
typedef VOID (APIENTRY * PFN_SETPROCTABLE)(PGLCLTPROCTABLE);
+/**
+ * Presentation data passed to opengl32!wglCbPresentBuffers.
+ *
+ * Pure software drivers don't need to worry about this -- if they stick to the
+ * GDI API then will integrate with the Desktop Window Manager (DWM) without
+ * problems. Hardware drivers, however, cannot present directly to the primary
+ * surface while the DWM is active, as DWM gets exclusive access to the primary
+ * surface.
+ *
+ * Proper DWM integration requires:
+ * - advertise the PFD_SUPPORT_COMPOSITION flag
+ * - redirect glFlush/glfinish/wglSwapBuffers into a surface shared with the
+ * DWM process.
+ *
+ * @sa http://www.opengl.org/pipeline/article/vol003_7/
+ * @sa http://blogs.msdn.com/greg_schechter/archive/2006/05/02/588934.aspx
+ */
+typedef struct _GLCBPRESENTBUFFERSDATA
+{
+ /**
+ * wglCbPresentBuffers enforces this to be 2.
+ */
+ DWORD magic1;
+
+ /**
+ * wglCbPresentBuffers enforces to be 0 or 1, but it is most commonly
+ * set to 0.
+ */
+ DWORD magic2;
+
+ /**
+ * Locally unique identifier (LUID) of the graphics adapter.
+ *
+ * This should contain the value returned by D3DKMTOpenAdapterFromHdc. It
+ * is passed to dwmapi!DwmpDxGetWindowSharedSurface in order to obtain
+ * the shared surface handle for the bound drawable (window).
+ *
+ * @sa http://msdn.microsoft.com/en-us/library/ms799177.aspx
+ */
+ LUID AdapterLuid;
+
+ /**
+ * This is passed unmodified to DrvPresentBuffers
+ */
+ LPVOID pPrivateData;
+
+ /**
+ * Client area rectangle to update, relative to the window upper-left corner.
+ */
+ RECT rect;
+} GLCBPRESENTBUFFERSDATA, *PGLCBPRESENTBUFFERSDATA;
+
+/**
+ * Callbacks supplied to DrvSetCallbackProcs by the OpenGL runtime.
+ *
+ * Pointers to several callback functions in opengl32.dll.
+ */
+typedef struct _GLCALLBACKTABLE
+{
+ /** Unused */
+ PROC wglCbSetCurrentValue;
+
+ /** Unused */
+ PROC wglCbGetCurrentValue;
+
+ /** Unused */
+ PROC wglCbGetDhglrc;
+
+ /** Unused */
+ PROC wglCbGetDdHandle;
+
+ /**
+ * Queue a present composition.
+ *
+ * Makes the runtime call DrvPresentBuffers with the composition information.
+ */
+ BOOL (APIENTRY *wglCbPresentBuffers)(HDC hdc, PGLCBPRESENTBUFFERSDATA data);
+
+} GLCALLBACKTABLE;
+
+typedef struct _GLPRESENTBUFFERSDATA
+{
+ /**
+ * The shared surface handle.
+ *
+ * Return by dwmapi!DwmpDxGetWindowSharedSurface.
+ *
+ * @sa http://channel9.msdn.com/forums/TechOff/251261-Help-Getting-the-shared-window-texture-out-of-DWM-/
+ */
+ HANDLE hSharedSurface;
+
+ LUID AdapterLuid;
+
+ /**
+ * Present history token.
+ *
+ * This is returned by dwmapi!DwmpDxGetWindowSharedSurface and
+ * should be passed to D3DKMTRender in D3DKMT_RENDER::PresentHistoryToken.
+ *
+ * @sa http://msdn.microsoft.com/en-us/library/ms799176.aspx
+ */
+ ULONGLONG PresentHistoryToken;
+
+ /** Same as GLCBPRESENTBUFFERSDATA::pPrivateData */
+ LPVOID pPrivateData;
+} GLPRESENTBUFFERSDATA, *PGLPRESENTBUFFERSDATA;
+
BOOL APIENTRY
DrvCopyContext(
DHGLRC dhrcSource,
@@ -435,6 +542,9 @@ DrvGetProcAddress(
LPCSTR lpszProc );
BOOL APIENTRY
+DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data);
+
+BOOL APIENTRY
DrvRealizeLayerPalette(
HDC hdc,
INT iLayerPlane,
diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c
index c296744838..7abe5d9f7f 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c
+++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c
@@ -34,9 +34,9 @@
#include "util/u_debug.h"
+#include "stw_icd.h"
#include "stw_device.h"
#include "stw_pixelformat.h"
-#include "stw_public.h"
#include "stw_tls.h"
@@ -154,8 +154,11 @@ stw_pixelformat_add(
pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
/* TODO: also support non-native pixel formats */
- pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW ;
-
+ pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
+
+ /* See http://www.opengl.org/pipeline/article/vol003_7/ */
+ pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
+
if (doublebuffer)
pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
@@ -288,12 +291,12 @@ stw_pixelformat_visual(GLvisual *visual,
}
-int
-stw_pixelformat_describe(
+LONG APIENTRY
+DrvDescribePixelFormat(
HDC hdc,
- int iPixelFormat,
- UINT nBytes,
- LPPIXELFORMATDESCRIPTOR ppfd )
+ INT iPixelFormat,
+ ULONG cjpfd,
+ PIXELFORMATDESCRIPTOR *ppfd )
{
uint count;
uint index;
@@ -306,7 +309,7 @@ stw_pixelformat_describe(
if (ppfd == NULL)
return count;
- if (index >= count || nBytes != sizeof( PIXELFORMATDESCRIPTOR ))
+ if (index >= count || cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
return 0;
pfi = stw_pixelformat_get_info( index );
@@ -316,6 +319,52 @@ stw_pixelformat_describe(
return count;
}
+BOOL APIENTRY
+DrvDescribeLayerPlane(
+ HDC hdc,
+ INT iPixelFormat,
+ INT iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd )
+{
+ assert(0);
+ return FALSE;
+}
+
+int APIENTRY
+DrvGetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ COLORREF *pcr )
+{
+ assert(0);
+ return 0;
+}
+
+int APIENTRY
+DrvSetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ CONST COLORREF *pcr )
+{
+ assert(0);
+ return 0;
+}
+
+BOOL APIENTRY
+DrvRealizeLayerPalette(
+ HDC hdc,
+ INT iLayerPlane,
+ BOOL bRealize )
+{
+ assert(0);
+ return FALSE;
+}
+
/* Only used by the wgl code, but have it here to avoid exporting the
* pixelformat.h functionality.
*/
diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h b/src/gallium/state_trackers/wgl/stw_pixelformat.h
index bec429231b..3a690b35ba 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h
+++ b/src/gallium/state_trackers/wgl/stw_pixelformat.h
@@ -30,6 +30,10 @@
#include <windows.h>
+#ifndef PFD_SUPPORT_COMPOSITION
+#define PFD_SUPPORT_COMPOSITION 0x00008000
+#endif
+
#include "main/mtypes.h"
#include "pipe/p_compiler.h"
@@ -62,4 +66,11 @@ void
stw_pixelformat_visual(GLvisual *visual,
const struct stw_pixelformat_info *pfi );
+int
+stw_pixelformat_choose( HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd );
+
+int
+stw_pixelformat_get(HDC hdc);
+
#endif /* STW_PIXELFORMAT_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.c b/src/gallium/state_trackers/wgl/stw_tls.c
index 4bd6a9289c..4bd6a9289c 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_tls.c
+++ b/src/gallium/state_trackers/wgl/stw_tls.c
diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.h b/src/gallium/state_trackers/wgl/stw_tls.h
index fbf8b1cbee..fbf8b1cbee 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_tls.h
+++ b/src/gallium/state_trackers/wgl/stw_tls.h
diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/stw_wgl.c
index a131292f7a..bb199fdd25 100644
--- a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c
+++ b/src/gallium/state_trackers/wgl/stw_wgl.c
@@ -28,7 +28,9 @@
#include <windows.h>
#include "util/u_debug.h"
-#include "shared/stw_public.h"
+#include "stw_icd.h"
+#include "stw_context.h"
+#include "stw_pixelformat.h"
#include "stw_wgl.h"
@@ -38,16 +40,16 @@ wglCopyContext(
HGLRC hglrcDst,
UINT mask )
{
- return stw_copy_context( (UINT_PTR)hglrcSrc,
- (UINT_PTR)hglrcDst,
- mask );
+ return DrvCopyContext( (DHGLRC)(UINT_PTR)hglrcSrc,
+ (DHGLRC)(UINT_PTR)hglrcDst,
+ mask );
}
WINGDIAPI HGLRC APIENTRY
wglCreateContext(
HDC hdc )
{
- return wglCreateLayerContext(hdc, 0);
+ return (HGLRC) DrvCreateContext(hdc);
}
WINGDIAPI HGLRC APIENTRY
@@ -55,21 +57,21 @@ wglCreateLayerContext(
HDC hdc,
int iLayerPlane )
{
- return (HGLRC) stw_create_layer_context( hdc, iLayerPlane );
+ return (HGLRC) DrvCreateLayerContext( hdc, iLayerPlane );
}
WINGDIAPI BOOL APIENTRY
wglDeleteContext(
HGLRC hglrc )
{
- return stw_delete_context( (UINT_PTR)hglrc );
+ return DrvDeleteContext((DHGLRC)(UINT_PTR)hglrc );
}
WINGDIAPI HGLRC APIENTRY
wglGetCurrentContext( VOID )
{
- return (HGLRC)stw_get_current_context();
+ return (HGLRC)(UINT_PTR)stw_get_current_context();
}
WINGDIAPI HDC APIENTRY
@@ -83,7 +85,7 @@ wglMakeCurrent(
HDC hdc,
HGLRC hglrc )
{
- return stw_make_current( hdc, (UINT_PTR)hglrc );
+ return DrvSetContext( hdc, (DHGLRC)(UINT_PTR)hglrc, NULL ) ? TRUE : FALSE;
}
@@ -91,7 +93,7 @@ WINGDIAPI BOOL APIENTRY
wglSwapBuffers(
HDC hdc )
{
- return stw_swap_buffers( hdc );
+ return DrvSwapBuffers( hdc );
}
@@ -100,14 +102,14 @@ wglSwapLayerBuffers(
HDC hdc,
UINT fuPlanes )
{
- return stw_swap_layer_buffers( hdc, fuPlanes );
+ return DrvSwapLayerBuffers( hdc, fuPlanes );
}
WINGDIAPI PROC APIENTRY
wglGetProcAddress(
LPCSTR lpszProc )
{
- return stw_get_proc_address( lpszProc );
+ return DrvGetProcAddress( lpszProc );
}
@@ -141,7 +143,7 @@ wglDescribePixelFormat(
UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd )
{
- return stw_pixelformat_describe( hdc, iPixelFormat, nBytes, ppfd );
+ return DrvDescribePixelFormat( hdc, iPixelFormat, nBytes, ppfd );
}
WINGDIAPI int APIENTRY
@@ -160,7 +162,7 @@ wglSetPixelFormat(
if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ))
return FALSE;
- return stw_pixelformat_set( hdc, iPixelFormat );
+ return DrvSetPixelFormat( hdc, iPixelFormat );
}
@@ -186,7 +188,8 @@ wglShareLists(
HGLRC hglrc1,
HGLRC hglrc2 )
{
- return stw_share_lists( (UINT_PTR)hglrc1, (UINT_PTR)hglrc2);;
+ return DrvShareLists((DHGLRC)(UINT_PTR)hglrc1,
+ (DHGLRC)(UINT_PTR)hglrc2);
}
WINGDIAPI BOOL APIENTRY
@@ -264,15 +267,7 @@ wglDescribeLayerPlane(
UINT nBytes,
LPLAYERPLANEDESCRIPTOR plpd )
{
- (void) hdc;
- (void) iPixelFormat;
- (void) iLayerPlane;
- (void) nBytes;
- (void) plpd;
-
- assert( 0 );
-
- return FALSE;
+ return DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
}
WINGDIAPI int APIENTRY
@@ -283,15 +278,7 @@ wglSetLayerPaletteEntries(
int cEntries,
CONST COLORREF *pcr )
{
- (void) hdc;
- (void) iLayerPlane;
- (void) iStart;
- (void) cEntries;
- (void) pcr;
-
- assert( 0 );
-
- return 0;
+ return DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
}
WINGDIAPI int APIENTRY
@@ -302,15 +289,7 @@ wglGetLayerPaletteEntries(
int cEntries,
COLORREF *pcr )
{
- (void) hdc;
- (void) iLayerPlane;
- (void) iStart;
- (void) cEntries;
- (void) pcr;
-
- assert( 0 );
-
- return 0;
+ return DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
}
WINGDIAPI BOOL APIENTRY
diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.h b/src/gallium/state_trackers/wgl/stw_wgl.h
index a98179944a..a98179944a 100644
--- a/src/gallium/state_trackers/wgl/wgl/stw_wgl.h
+++ b/src/gallium/state_trackers/wgl/stw_wgl.h
diff --git a/src/gallium/state_trackers/wgl/shared/stw_winsys.h b/src/gallium/state_trackers/wgl/stw_winsys.h
index c0bf82c9ed..1ead47d6e6 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_winsys.h
+++ b/src/gallium/state_trackers/wgl/stw_winsys.h
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008-2009 Vmware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
* 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
+ * 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.
@@ -36,6 +36,8 @@ struct pipe_screen;
struct pipe_context;
struct pipe_surface;
+struct stw_shared_surface;
+
struct stw_winsys
{
struct pipe_screen *
@@ -44,10 +46,52 @@ struct stw_winsys
struct pipe_context *
(*create_context)( struct pipe_screen *screen );
+ /**
+ * Present the color buffer to the window associated with the device context.
+ */
+ void
+ (*present)( struct pipe_screen *screen,
+ struct pipe_surface *surf,
+ HDC hDC );
+
+ /**
+ * Locally unique identifier (LUID) of the graphics adapter.
+ *
+ * @sa GLCBPRESENTBUFFERSDATA::AdapterLuid;
+ */
+ boolean
+ (*get_adapter_luid)( struct pipe_screen *screen,
+ LUID *pAdapterLuid );
+
+ /**
+ * Open a shared surface (optional).
+ *
+ * @sa GLCBPRESENTBUFFERSDATA::hSharedSurface;
+ */
+ struct stw_shared_surface *
+ (*shared_surface_open)(struct pipe_screen *screen,
+ HANDLE hSharedSurface);
+
+ /**
+ * Open a shared surface (optional).
+ */
+ void
+ (*shared_surface_close)(struct pipe_screen *screen,
+ struct stw_shared_surface *surface);
+
+ /**
+ * Compose into a shared (optional).
+ *
+ * Blit the color buffer into a shared surface.
+ *
+ * @sa GLPRESENTBUFFERSDATA::PresentHistoryToken.
+ */
void
- (*flush_frontbuffer)( struct pipe_screen *screen,
- struct pipe_surface *surf,
- HDC hDC );
+ (*compose)( struct pipe_screen *screen,
+ struct pipe_surface *src,
+ struct stw_shared_surface *dest,
+ LPCRECT pRect,
+ ULONGLONG PresentHistoryToken );
};
boolean
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
index c708ac3170..7037d17e43 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.c
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -4,6 +4,7 @@
#include "cso_cache/cso_context.h"
#include "util/u_draw_quad.h"
+#include "util/u_math.h"
#include "pipe/p_inlines.h"
@@ -11,9 +12,9 @@ struct xorg_composite_blend {
int op:8;
unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
- unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
-
unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+
+ unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
};
@@ -40,22 +41,20 @@ static const struct xorg_composite_blend xorg_blends[] = {
PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
};
+
static INLINE void
-pixel_to_float4(PictFormatPtr format,
- CARD32 pixel, float *color)
+pixel_to_float4(Pixel pixel, float *color)
{
CARD32 r, g, b, a;
- debug_assert(format->type == PictTypeDirect);
-
- r = (pixel >> format->direct.red) & format->direct.redMask;
- g = (pixel >> format->direct.green) & format->direct.greenMask;
- b = (pixel >> format->direct.blue) & format->direct.blueMask;
- a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
- color[0] = ((float)r) / ((float)format->direct.redMask);
- color[1] = ((float)g) / ((float)format->direct.greenMask);
- color[2] = ((float)b) / ((float)format->direct.blueMask);
- color[3] = ((float)a) / ((float)format->direct.alphaMask);
+ a = (pixel >> 24) & 0xff;
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8) & 0xff;
+ b = (pixel >> 0) & 0xff;
+ color[0] = ((float)r) / 255.;
+ color[1] = ((float)g) / 255.;
+ color[2] = ((float)b) / 255.;
+ color[3] = ((float)a) / 255.;
}
struct acceleration_info {
@@ -133,24 +132,22 @@ setup_vertex_data0(struct exa_context *ctx,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
- float vertices[4][2][4];
-
/* 1st vertex */
- setup_vertex0(vertices[0], dstX, dstY,
+ setup_vertex0(ctx->vertices2[0], dstX, dstY,
ctx->solid_color);
/* 2nd vertex */
- setup_vertex0(vertices[1], dstX + width, dstY,
+ setup_vertex0(ctx->vertices2[1], dstX + width, dstY,
ctx->solid_color);
/* 3rd vertex */
- setup_vertex0(vertices[2], dstX + width, dstY + height,
+ setup_vertex0(ctx->vertices2[2], dstX + width, dstY + height,
ctx->solid_color);
/* 4th vertex */
- setup_vertex0(vertices[3], dstX, dstY + height,
+ setup_vertex0(ctx->vertices2[3], dstX, dstY + height,
ctx->solid_color);
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ ctx->vertices2,
+ sizeof(ctx->vertices2));
}
static INLINE void
@@ -172,7 +169,6 @@ setup_vertex_data1(struct exa_context *ctx,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
- float vertices[4][2][4];
float s0, t0, s1, t1;
struct pipe_texture *src = ctx->bound_textures[0];
@@ -182,24 +178,49 @@ setup_vertex_data1(struct exa_context *ctx,
t1 = srcY + height / src->height[0];
/* 1st vertex */
- setup_vertex1(vertices[0], dstX, dstY,
+ setup_vertex1(ctx->vertices2[0], dstX, dstY,
+ s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(ctx->vertices2[1], dstX + width, dstY,
+ s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(ctx->vertices2[2], dstX + width, dstY + height,
+ s1, t1);
+ /* 4th vertex */
+ setup_vertex1(ctx->vertices2[3], dstX, dstY + height,
+ s0, t1);
+
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ ctx->vertices2,
+ sizeof(ctx->vertices2));
+}
+
+static struct pipe_buffer *
+setup_vertex_data_tex(struct exa_context *ctx,
+ float x0, float y0, float x1, float y1,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ /* 1st vertex */
+ setup_vertex1(ctx->vertices2[0], x0, y0,
s0, t0);
/* 2nd vertex */
- setup_vertex1(vertices[1], dstX + width, dstY,
+ setup_vertex1(ctx->vertices2[1], x1, y0,
s1, t0);
/* 3rd vertex */
- setup_vertex1(vertices[2], dstX + width, dstY + height,
+ setup_vertex1(ctx->vertices2[2], x1, y1,
s1, t1);
/* 4th vertex */
- setup_vertex1(vertices[3], dstX, dstY + height,
+ setup_vertex1(ctx->vertices2[3], x0, y1,
s0, t1);
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ ctx->vertices2,
+ sizeof(ctx->vertices2));
}
+
static INLINE void
setup_vertex2(float vertex[3][4], float x, float y,
float s0, float t0, float s1, float t1)
@@ -225,7 +246,6 @@ setup_vertex_data2(struct exa_context *ctx,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
- float vertices[4][3][4];
float st0[4], st1[4];
struct pipe_texture *src = ctx->bound_textures[0];
struct pipe_texture *mask = ctx->bound_textures[0];
@@ -241,21 +261,21 @@ setup_vertex_data2(struct exa_context *ctx,
st1[3] = maskY + height / mask->height[0];
/* 1st vertex */
- setup_vertex2(vertices[0], dstX, dstY,
+ setup_vertex2(ctx->vertices3[0], dstX, dstY,
st0[0], st0[1], st1[0], st1[1]);
/* 2nd vertex */
- setup_vertex2(vertices[1], dstX + width, dstY,
+ setup_vertex2(ctx->vertices3[1], dstX + width, dstY,
st0[2], st0[1], st1[2], st1[1]);
/* 3rd vertex */
- setup_vertex2(vertices[2], dstX + width, dstY + height,
+ setup_vertex2(ctx->vertices3[2], dstX + width, dstY + height,
st0[2], st0[3], st1[2], st1[3]);
/* 4th vertex */
- setup_vertex2(vertices[3], dstX, dstY + height,
+ setup_vertex2(ctx->vertices3[3], dstX, dstY + height,
st0[0], st0[3], st1[0], st1[3]);
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ ctx->vertices3,
+ sizeof(ctx->vertices3));
}
boolean xorg_composite_accelerated(int op,
@@ -267,22 +287,25 @@ boolean xorg_composite_accelerated(int op,
unsigned accel_ops_count =
sizeof(accelerated_ops)/sizeof(struct acceleration_info);
-
- /*FIXME: currently accel is disabled */
- return FALSE;
-
- if (pSrcPicture) {
- /* component alpha not supported */
- if (pSrcPicture->componentAlpha)
+ if (pSrcPicture->pSourcePict) {
+ /* Gradients not yet supported */
+ if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
return FALSE;
- /* fills not supported */
- if (pSrcPicture->pSourcePict)
+
+ /* Solid source with mask not yet handled properly */
+ if (pMaskPicture)
return FALSE;
}
for (i = 0; i < accel_ops_count; ++i) {
if (op == accelerated_ops[i].op) {
- if (pMaskPicture && !accelerated_ops[i].with_mask)
+ /* Check for unsupported component alpha */
+ if ((pSrcPicture->componentAlpha &&
+ !accelerated_ops[i].component_alpha) ||
+ (pMaskPicture &&
+ (!accelerated_ops[i].with_mask ||
+ (pMaskPicture->componentAlpha &&
+ !accelerated_ops[i].component_alpha))))
return FALSE;
return TRUE;
}
@@ -291,16 +314,20 @@ boolean xorg_composite_accelerated(int op,
}
static void
-bind_framebuffer_state(struct exa_context *exa, PicturePtr pDstPicture,
- struct exa_pixmap_priv *pDst)
+bind_clip_state(struct exa_context *exa)
+{
+}
+
+static void
+bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
unsigned i;
struct pipe_framebuffer_state state;
struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
memset(&state, 0, sizeof(struct pipe_framebuffer_state));
- state.width = pDstPicture->pDrawable->width;
- state.height = pDstPicture->pDrawable->height;
+ state.width = pDst->tex->width[0];
+ state.height = pDst->tex->height[0];
state.nr_cbufs = 1;
state.cbufs[0] = surface;
@@ -311,6 +338,9 @@ bind_framebuffer_state(struct exa_context *exa, PicturePtr pDstPicture,
state.zsbuf = 0;
cso_set_framebuffer(exa->cso, &state);
+
+ /* we do fire and forget for the framebuffer, this is the forget part */
+ pipe_surface_reference(&surface, NULL);
}
enum AxisOrientation {
@@ -338,10 +368,12 @@ set_viewport(struct exa_context *exa, int width, int height,
}
static void
-bind_viewport_state(struct exa_context *exa, PicturePtr pDstPicture)
+bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
- int width = pDstPicture->pDrawable->width;
- int height = pDstPicture->pDrawable->height;
+ int width = pDst->tex->width[0];
+ int height = pDst->tex->height[0];
+
+ /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
set_viewport(exa, width, height, Y0_TOP);
}
@@ -350,13 +382,9 @@ static void
bind_blend_state(struct exa_context *exa, int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture)
{
- boolean component_alpha = pSrcPicture->componentAlpha;
struct xorg_composite_blend blend_opt;
struct pipe_blend_state blend;
- if (component_alpha) {
- op = PictOpOver;
- }
blend_opt = blend_for_op(op);
memset(&blend, 0, sizeof(struct pipe_blend_state));
@@ -390,14 +418,17 @@ bind_shaders(struct exa_context *exa, int op,
unsigned vs_traits = 0, fs_traits = 0;
struct xorg_shader shader;
+ exa->has_solid_color = FALSE;
+
if (pSrcPicture) {
if (pSrcPicture->pSourcePict) {
if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
fs_traits |= FS_SOLID_FILL;
vs_traits |= VS_SOLID_FILL;
- pixel_to_float4(pSrcPicture->pFormat,
- pSrcPicture->pSourcePict->solidFill.color,
+ debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
+ pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
exa->solid_color);
+ exa->has_solid_color = TRUE;
} else {
debug_assert("!gradients not supported");
}
@@ -434,6 +465,12 @@ bind_samplers(struct exa_context *exa, int op,
memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
+ if ((pSrc && exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE) ||
+ (pMask && exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE))
+ exa->pipe->flush(exa->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
if (pSrcPicture && pSrc) {
unsigned src_wrap = render_repeat_to_gallium(
pSrcPicture->repeatType);
@@ -478,15 +515,15 @@ setup_vs_constant_buffer(struct exa_context *exa,
struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16,
+ cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
- pipe_buffer_write(exa->ctx->screen, cbuf->buffer,
+ pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
0, param_bytes, vs_consts);
}
- exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_VERTEX, 0, cbuf);
+ exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
}
@@ -500,22 +537,22 @@ setup_fs_constant_buffer(struct exa_context *exa)
struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer;
pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16,
+ cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
- pipe_buffer_write(exa->ctx->screen, cbuf->buffer,
+ pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
0, param_bytes, fs_consts);
}
- exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
}
static void
-setup_constant_buffers(struct exa_context *exa, PicturePtr pDstPicture)
+setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
- int width = pDstPicture->pDrawable->width;
- int height = pDstPicture->pDrawable->height;
+ int width = pDst->tex->width[0];
+ int height = pDst->tex->height[0];
setup_vs_constant_buffer(exa, width, height);
setup_fs_constant_buffer(exa);
@@ -530,15 +567,15 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
struct exa_pixmap_priv *pMask,
struct exa_pixmap_priv *pDst)
{
- bind_framebuffer_state(exa, pDstPicture, pDst);
- bind_viewport_state(exa, pDstPicture);
+ bind_framebuffer_state(exa, pDst);
+ bind_viewport_state(exa, pDst);
bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
bind_rasterizer_state(exa);
bind_shaders(exa, op, pSrcPicture, pMaskPicture);
bind_samplers(exa, op, pSrcPicture, pMaskPicture,
pDstPicture, pSrc, pMask, pDst);
-
- setup_constant_buffers(exa, pDstPicture);
+ bind_clip_state(exa);
+ setup_constant_buffers(exa, pDst);
return FALSE;
}
@@ -548,7 +585,7 @@ void xorg_composite(struct exa_context *exa,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
- struct pipe_context *pipe = exa->ctx;
+ struct pipe_context *pipe = exa->pipe;
struct pipe_buffer *buf = 0;
if (exa->num_bound_samplers == 0 ) { /* solid fill */
@@ -573,12 +610,457 @@ void xorg_composite(struct exa_context *exa,
}
if (buf) {
+ int num_attribs = 1; /*pos*/
+ num_attribs += exa->num_bound_samplers;
+ if (exa->has_solid_color)
+ ++num_attribs;
+
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
- 1 + exa->num_bound_samplers); /* attribs/vert */
+ num_attribs); /* attribs/vert */
pipe_buffer_reference(&buf, NULL);
}
}
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg)
+{
+ unsigned vs_traits, fs_traits;
+ struct xorg_shader shader;
+
+ pixel_to_float4(fg, exa->solid_color);
+ exa->has_solid_color = TRUE;
+
+ exa->solid_color[3] = 1.f;
+
+#if 0
+ debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
+ (fg >> 24) & 0xff, (fg >> 16) & 0xff,
+ (fg >> 8) & 0xff, (fg >> 0) & 0xff,
+ exa->solid_color[0], exa->solid_color[1],
+ exa->solid_color[2], exa->solid_color[3]);
+#endif
+
+ vs_traits = VS_SOLID_FILL;
+ fs_traits = FS_SOLID_FILL;
+
+ bind_framebuffer_state(exa, pixmap);
+ bind_viewport_state(exa, pixmap);
+ bind_rasterizer_state(exa);
+ bind_blend_state(exa, PictOpSrc, NULL, NULL);
+ setup_constant_buffers(exa, pixmap);
+ bind_clip_state(exa);
+
+ shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+
+ return TRUE;
+}
+
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1)
+{
+ struct pipe_context *pipe = exa->pipe;
+ struct pipe_buffer *buf = 0;
+
+ /* 1st vertex */
+ setup_vertex0(exa->vertices2[0], x0, y0,
+ exa->solid_color);
+ /* 2nd vertex */
+ setup_vertex0(exa->vertices2[1], x1, y0,
+ exa->solid_color);
+ /* 3rd vertex */
+ setup_vertex0(exa->vertices2[2], x1, y1,
+ exa->solid_color);
+ /* 4th vertex */
+ setup_vertex0(exa->vertices2[3], x0, y1,
+ exa->solid_color);
+
+ buf = pipe_user_buffer_create(exa->pipe->screen,
+ exa->vertices2,
+ sizeof(exa->vertices2));
+
+
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+
+static INLINE void shift_rectx(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[0] += shift;
+ coords[2] -= shift;
+ if (bounds) {
+ coords[2] = MIN2(coords[2], bounds[2]);
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ }
+}
+
+static INLINE void shift_recty(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[1] += shift;
+ coords[3] -= shift;
+ if (bounds) {
+ coords[3] = MIN2(coords[3], bounds[3]);
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+ }
+}
+
+static INLINE void bound_rect(float coords[4],
+ const float bounds[4],
+ float shift[4])
+{
+ /* if outside the bounds */
+ if (coords[0] > (bounds[0] + bounds[2]) ||
+ coords[1] > (bounds[1] + bounds[3]) ||
+ (coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ shift[0] = 0.f;
+ shift[1] = 0.f;
+ return;
+ }
+
+ /* bound x */
+ if (coords[0] < bounds[0]) {
+ shift[0] = bounds[0] - coords[0];
+ coords[2] -= shift[0];
+ coords[0] = bounds[0];
+ } else
+ shift[0] = 0.f;
+
+ /* bound y */
+ if (coords[1] < bounds[1]) {
+ shift[1] = bounds[1] - coords[1];
+ coords[3] -= shift[1];
+ coords[1] = bounds[1];
+ } else
+ shift[1] = 0.f;
+
+ shift[2] = bounds[2] - coords[2];
+ shift[3] = bounds[3] - coords[3];
+ /* bound width/height */
+ coords[2] = MIN2(coords[2], bounds[2]);
+ coords[3] = MIN2(coords[3], bounds[3]);
+
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+
+ /* if outside the bounds */
+ if ((coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ return;
+ }
+}
+
+static INLINE void sync_size(float *src_loc, float *dst_loc)
+{
+ src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
+ src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
+ dst_loc[2] = src_loc[2];
+ dst_loc[3] = src_loc[3];
+}
+
+
+static void renderer_copy_texture(struct exa_context *exa,
+ struct pipe_texture *src,
+ float sx1, float sy1,
+ float sx2, float sy2,
+ struct pipe_texture *dst,
+ float dx1, float dy1,
+ float dx2, float dy2)
+{
+ struct pipe_context *pipe = exa->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *buf;
+ struct pipe_surface *dst_surf = screen->get_tex_surface(
+ screen, dst, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct pipe_framebuffer_state fb;
+ float s0, t0, s1, t1;
+ struct xorg_shader shader;
+
+ assert(src->width[0] != 0);
+ assert(src->height[0] != 0);
+ assert(dst->width[0] != 0);
+ assert(dst->height[0] != 0);
+
+#if 1
+ s0 = sx1 / src->width[0];
+ s1 = sx2 / src->width[0];
+ t0 = sy1 / src->height[0];
+ t1 = sy2 / src->height[0];
+#else
+ s0 = 0;
+ s1 = 1;
+ t0 = 0;
+ t1 = 1;
+#endif
+
+#if 0
+ debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
+ sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
+ s0, t0, s1, t1);
+#endif
+
+ assert(screen->is_format_supported(screen, dst_surf->format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ 0));
+
+ /* save state (restored below) */
+ cso_save_blend(exa->cso);
+ cso_save_samplers(exa->cso);
+ cso_save_sampler_textures(exa->cso);
+ cso_save_framebuffer(exa->cso);
+ cso_save_fragment_shader(exa->cso);
+ cso_save_vertex_shader(exa->cso);
+
+ cso_save_viewport(exa->cso);
+
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(exa->cso, &blend);
+ }
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ 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_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ cso_single_sampler(exa->cso, 0, &sampler);
+ cso_single_sampler_done(exa->cso);
+ }
+
+ set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP);
+
+ /* texture */
+ cso_set_sampler_textures(exa->cso, 1, &src);
+
+ bind_rasterizer_state(exa);
+
+ /* shaders */
+ shader = xorg_shaders_get(exa->shaders,
+ VS_COMPOSITE,
+ FS_COMPOSITE);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst_surf->width;
+ fb.height = dst_surf->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst_surf;
+ {
+ int i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(exa->cso, &fb);
+ setup_vs_constant_buffer(exa, fb.width, fb.height);
+ setup_fs_constant_buffer(exa);
+
+ /* draw quad */
+ buf = setup_vertex_data_tex(exa,
+ dx1, dy1,
+ dx2, dy2,
+ s0, t0, s1, t1,
+ 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(exa->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+
+ /* restore state we changed */
+ cso_restore_blend(exa->cso);
+ cso_restore_samplers(exa->cso);
+ cso_restore_sampler_textures(exa->cso);
+ cso_restore_framebuffer(exa->cso);
+ cso_restore_vertex_shader(exa->cso);
+ cso_restore_fragment_shader(exa->cso);
+ cso_restore_viewport(exa->cso);
+
+ pipe_surface_reference(&dst_surf, NULL);
+}
+
+
+static struct pipe_texture *
+create_sampler_texture(struct exa_context *ctx,
+ struct pipe_texture *src)
+{
+ enum pipe_format format;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *pt;
+ struct pipe_texture templ;
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* the coming in texture should already have that invariance */
+ debug_assert(screen->is_format_supported(screen, src->format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+
+ format = src->format;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = format;
+ templ.last_level = 0;
+ templ.width[0] = src->width[0];
+ templ.height[0] = src->height[0];
+ templ.depth[0] = 1;
+ pf_get_block(format, &templ.block);
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ pt = screen->texture_create(screen, &templ);
+
+ debug_assert(!pt || pipe_is_referenced(&pt->reference));
+
+ if (!pt)
+ return NULL;
+
+ {
+ /* copy source framebuffer surface into texture */
+ struct pipe_surface *ps_read = screen->get_tex_surface(
+ screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
+ struct pipe_surface *ps_tex = screen->get_tex_surface(
+ screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE );
+ pipe->surface_copy(pipe,
+ ps_tex, /* dest */
+ 0, 0, /* destx/y */
+ ps_read,
+ 0, 0, src->width[0], src->height[0]);
+ pipe_surface_reference(&ps_read, NULL);
+ pipe_surface_reference(&ps_tex, NULL);
+ }
+
+ return pt;
+}
+
+void xorg_copy_pixmap(struct exa_context *ctx,
+ struct exa_pixmap_priv *dst_priv, int dx, int dy,
+ struct exa_pixmap_priv *src_priv, int sx, int sy,
+ int width, int height)
+{
+ float dst_loc[4], src_loc[4];
+ float dst_bounds[4], src_bounds[4];
+ float src_shift[4], dst_shift[4], shift[4];
+ struct pipe_texture *dst = dst_priv->tex;
+ struct pipe_texture *src = src_priv->tex;
+
+ if (ctx->pipe->is_texture_referenced(ctx->pipe, src, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE)
+ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+ dst_bounds[0] = 0.f;
+ dst_bounds[1] = 0.f;
+ dst_bounds[2] = dst->width[0];
+ dst_bounds[3] = dst->height[0];
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+ src_bounds[0] = 0.f;
+ src_bounds[1] = 0.f;
+ src_bounds[2] = src->width[0];
+ src_bounds[3] = src->height[0];
+
+ bound_rect(src_loc, src_bounds, src_shift);
+ bound_rect(dst_loc, dst_bounds, dst_shift);
+ shift[0] = src_shift[0] - dst_shift[0];
+ shift[1] = src_shift[1] - dst_shift[1];
+
+ if (shift[0] < 0)
+ shift_rectx(src_loc, src_bounds, -shift[0]);
+ else
+ shift_rectx(dst_loc, dst_bounds, shift[0]);
+
+ if (shift[1] < 0)
+ shift_recty(src_loc, src_bounds, -shift[1]);
+ else
+ shift_recty(dst_loc, dst_bounds, shift[1]);
+
+ sync_size(src_loc, dst_loc);
+
+ if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
+ dst_loc[2] >= 0 && dst_loc[3] >= 0) {
+ struct pipe_texture *temp_src = src;
+
+ if (src == dst)
+ temp_src = create_sampler_texture(ctx, src);
+
+ renderer_copy_texture(ctx,
+ temp_src,
+ src_loc[0],
+ src_loc[1],
+ src_loc[0] + src_loc[2],
+ src_loc[1] + src_loc[3],
+ dst,
+ dst_loc[0],
+ dst_loc[1],
+ dst_loc[0] + dst_loc[2],
+ dst_loc[1] + dst_loc[3]);
+
+ if (src == dst)
+ pipe_texture_reference(&temp_src, NULL);
+ }
+}
+
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h
index 17dfcb199e..e73f1c704a 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.h
+++ b/src/gallium/state_trackers/xorg/xorg_composite.h
@@ -22,4 +22,16 @@ void xorg_composite(struct exa_context *exa,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height);
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg);
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1);
+
+void xorg_copy_pixmap(struct exa_context *ctx,
+ struct exa_pixmap_priv *dst, int dx, int dy,
+ struct exa_pixmap_priv *src, int sx, int sy,
+ int width, int height);
+
#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
index fe08bde9ef..67fe29a69d 100644
--- a/src/gallium/state_trackers/xorg/xorg_crtc.c
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -42,8 +42,12 @@
#include "xorg_tracker.h"
#include "xf86Modes.h"
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#endif
#include "pipe/p_inlines.h"
#include "util/u_rect.h"
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
index 6431a0fe25..8a362596c7 100644
--- a/src/gallium/state_trackers/xorg/xorg_dri2.c
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -118,6 +118,7 @@ driDoCreateBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format)
}
if (!tex) {
+ exaMoveInPixmap(private->pPixmap);
xorg_exa_set_shared_usage(private->pPixmap);
pScreen->ModifyPixmapHeader(private->pPixmap, 0, 0, 0, 0, 0, NULL);
tex = xorg_exa_get_texture(private->pPixmap);
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index 643b6b3b9e..3dff8d859e 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -558,6 +558,7 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
xf86SetBlackWhitePixels(pScreen);
ms->exa = xorg_exa_init(pScrn);
+ ms->debug_fallback = debug_get_option_bool("XORG_DEBUG_FALLBACK", TRUE);
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index a17a71f23a..b54e31a701 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -47,6 +47,10 @@
#include "util/u_rect.h"
+#define DEBUG_PRINT 0
+#define DEBUG_SOLID 0
+#define DISABLE_ACCEL 0
+
/*
* Helper functions
*/
@@ -72,6 +76,9 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
assert(*bbp == 16);
break;
case 8:
+ *format = PIPE_FORMAT_I8_UNORM;
+ assert(*bbp == 8);
+ break;
case 4:
case 1:
*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
@@ -82,6 +89,25 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
}
}
+static void
+xorg_exa_init_state(struct exa_context *exa)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ /* set common initial clip state */
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+ cso_set_depth_stencil_alpha(exa->cso, &dsa);
+}
+
+static void
+xorg_exa_common_done(struct exa_context *exa)
+{
+ exa->copy.src = NULL;
+ exa->copy.dst = NULL;
+ exa->has_solid_color = FALSE;
+ exa->num_bound_samplers = 0;
+}
+
/*
* Static exported EXA functions
*/
@@ -111,9 +137,9 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
if (!priv || !priv->tex)
return FALSE;
- if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
- exa->ctx->flush(exa->ctx, 0, NULL);
+ exa->pipe->flush(exa->pipe, 0, NULL);
transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
PIPE_TRANSFER_READ, x, y, w, h);
@@ -178,9 +204,9 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
if (priv->map_count++ == 0)
{
- if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
- exa->ctx->flush(exa->ctx, 0, NULL);
+ exa->pipe->flush(exa->pipe, 0, NULL);
priv->map_transfer =
exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
@@ -231,15 +257,22 @@ ExaDone(PixmapPtr pPixmap)
if (!priv)
return;
- if (priv->src_surf)
- exa->scrn->tex_surface_destroy(priv->src_surf);
- priv->src_surf = NULL;
+#if 1
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
+#else
+ xorg_exa_finish(exa);
+#endif
+ xorg_exa_common_done(exa);
}
static void
ExaDoneComposite(PixmapPtr pPixmap)
{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ xorg_exa_common_done(exa);
}
static Bool
@@ -250,24 +283,36 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
struct exa_context *exa = ms->exa;
- if (pPixmap->drawable.depth < 15)
- return FALSE;
-
- if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
- return FALSE;
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareSolid(0x%x)\n", fg);
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("solid accle not enabled");
if (!priv || !priv->tex)
- return FALSE;
+ XORG_FALLBACK("solid !priv || !priv->tex");
+
+ if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
+ XORG_FALLBACK("solid planeMask is not solid");
if (alu != GXcopy)
- return FALSE;
+ XORG_FALLBACK("solid not GXcopy");
- if (!exa->ctx || !exa->ctx->surface_fill)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ XORG_FALLBACK("solid bad format %s", pf_name(priv->tex->format));
+ }
- priv->color = fg;
+#if DEBUG_SOLID
+ fg = 0xffff0000;
+#endif
- return TRUE;
+#if DISABLE_ACCEL
+ return FALSE;
+#else
+ return xorg_solid_bind_state(exa, priv, fg);
+#endif
}
static void
@@ -277,12 +322,51 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_context *exa = ms->exa;
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct pipe_surface *surf = exa_gpu_surface(exa, priv);
- exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
- priv->color);
+#if DEBUG_PRINT
+ debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
+#endif
+
+#if 0
+ if (x0 == 0 && y0 == 0 &&
+ x1 == priv->tex->width[0] &&
+ y1 == priv->tex->height[0]) {
+ exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
+ exa->solid_color, 1., 0);
+ } else
+#endif
- exa->scrn->tex_surface_destroy(surf);
+#if DEBUG_SOLID
+ exa->solid_color[0] = 0.f;
+ exa->solid_color[1] = 1.f;
+ exa->solid_color[2] = 0.f;
+ exa->solid_color[3] = 1.f;
+ xorg_solid(exa, priv, 0, 0, 1024, 768);
+ exa->solid_color[0] = 1.f;
+ exa->solid_color[1] = 0.f;
+ exa->solid_color[2] = 0.f;
+ exa->solid_color[3] = 1.f;
+ xorg_solid(exa, priv, 0, 0, 300, 300);
+ xorg_solid(exa, priv, 300, 300, 350, 350);
+ xorg_solid(exa, priv, 350, 350, 500, 500);
+
+ xorg_solid(exa, priv,
+ priv->tex->width[0] - 10,
+ priv->tex->height[0] - 10,
+ priv->tex->width[0],
+ priv->tex->height[0]);
+
+ exa->solid_color[0] = 0.f;
+ exa->solid_color[1] = 0.f;
+ exa->solid_color[2] = 1.f;
+ exa->solid_color[3] = 1.f;
+
+ exa->has_solid_color = FALSE;
+ ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
+ ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
+#else
+ xorg_solid(exa, priv, x0, y0, x1, y1) ;
+#endif
}
static Bool
@@ -295,42 +379,63 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
- if (alu != GXcopy)
- return FALSE;
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareCopy\n");
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("copy accle not enabled");
- if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
- return FALSE;
+ if (!priv || !src_priv)
+ XORG_FALLBACK("copy !priv || !src_priv");
+
+ if (!priv->tex || !src_priv->tex)
+ XORG_FALLBACK("copy !priv->tex || !src_priv->tex");
if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
- return FALSE;
+ XORG_FALLBACK("copy planeMask is not solid");
- if (!priv || !src_priv)
- return FALSE;
+ if (alu != GXcopy)
+ XORG_FALLBACK("copy alu not GXcopy");
- if (!priv->tex || !src_priv->tex)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+ XORG_FALLBACK("copy pDst format %s", pf_name(priv->tex->format));
- if (!exa->ctx || !exa->ctx->surface_copy)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
+ src_priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("copy pSrc format %s", pf_name(src_priv->tex->format));
- priv->src_surf = exa_gpu_surface(exa, src_priv);
+ exa->copy.src = src_priv;
+ exa->copy.dst = priv;
+#if DISABLE_ACCEL
+ return FALSE;
+#else
return TRUE;
+#endif
}
static void
ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
int width, int height)
{
- ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
- modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_context *exa = ms->exa;
- struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
- struct pipe_surface *surf = exa_gpu_surface(exa, priv);
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+
+#if DEBUG_PRINT
+ debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
+ srcX, srcY, dstX, dstY, width, height);
+#endif
+
+ debug_assert(priv == exa->copy.dst);
- exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
- srcX, srcY, width, height);
- exa->scrn->tex_surface_destroy(surf);
+ xorg_copy_pixmap(exa, exa->copy.dst, dstX, dstY,
+ exa->copy.src, srcX, srcY,
+ width, height);
}
static Bool
@@ -341,12 +446,55 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
+
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareComposite\n");
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("comp accle not enabled");
+
+ priv = exaGetPixmapDriverPrivate(pDst);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("comp pDst %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+ XORG_FALLBACK("copy pDst format: %s", pf_name(priv->tex->format));
+
+ if (pSrc) {
+ priv = exaGetPixmapDriverPrivate(pSrc);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("comp pSrc %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("copy pSrc format: %s", pf_name(priv->tex->format));
+ }
+
+ if (pMask) {
+ priv = exaGetPixmapDriverPrivate(pMask);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("comp pMask %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("copy pMask format: %s", pf_name(priv->tex->format));
+ }
+#if DISABLE_ACCEL
+ (void) exa;
+ return FALSE;
+#else
return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
pDstPicture,
- exaGetPixmapDriverPrivate(pSrc),
- exaGetPixmapDriverPrivate(pMask),
+ pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
+ pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
exaGetPixmapDriverPrivate(pDst));
+#endif
}
static void
@@ -358,6 +506,10 @@ ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
struct exa_context *exa = ms->exa;
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
+#if DEBUG_PRINT
+ debug_printf("\tExaComposite\n");
+#endif
+
xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
dstX, dstY, width, height);
}
@@ -367,10 +519,15 @@ ExaCheckComposite(int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
- return xorg_composite_accelerated(op,
- pSrcPicture,
- pMaskPicture,
- pDstPicture);
+ boolean accelerated = xorg_composite_accelerated(op,
+ pSrcPicture,
+ pMaskPicture,
+ pDstPicture);
+#if DEBUG_PRINT
+ debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
+ op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
+#endif
+ return accelerated;
}
static void *
@@ -389,14 +546,11 @@ static void
ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
{
struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- modesettingPtr ms = modesettingPTR(pScrn);
if (!priv)
return;
- if (priv->tex)
- ms->screen->texture_destroy(priv->tex);
+ pipe_texture_reference(&priv->tex, NULL);
xfree(priv);
}
@@ -537,16 +691,16 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
if (priv->tex) {
struct pipe_surface *dst_surf;
-
- dst_surf = exa->scrn->get_tex_surface(exa->scrn, texture, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_WRITE);
- priv->src_surf = exa_gpu_surface(exa, priv);
- exa->ctx->surface_copy(exa->ctx, dst_surf, 0, 0, priv->src_surf,
- 0, 0, min(width, texture->width[0]),
- min(height, texture->height[0]));
+ struct pipe_surface *src_surf;
+
+ dst_surf = exa->scrn->get_tex_surface(
+ exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
+ src_surf = exa_gpu_surface(exa, priv);
+ exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
+ 0, 0, min(width, texture->width[0]),
+ min(height, texture->height[0]));
exa->scrn->tex_surface_destroy(dst_surf);
- exa->scrn->tex_surface_destroy(priv->src_surf);
- priv->src_surf = NULL;
+ exa->scrn->tex_surface_destroy(src_surf);
} else if (pPixmap->devPrivate.ptr) {
struct pipe_transfer *transfer;
@@ -563,6 +717,9 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
pPixmap->devKind, 0, 0);
exa->scrn->transfer_unmap(exa->scrn, transfer);
exa->scrn->tex_transfer_destroy(transfer);
+
+ xfree(pPixmap->devPrivate.ptr);
+ pPixmap->devPrivate.ptr = NULL;
}
}
#ifdef DRM_MODE_FEATURE_DIRTYFB
@@ -574,6 +731,8 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
#endif
pipe_texture_reference(&priv->tex, texture);
+ /* the texture we create has one reference */
+ pipe_texture_reference(&texture, NULL);
}
return TRUE;
@@ -611,8 +770,8 @@ xorg_exa_close(ScrnInfoPtr pScrn)
cso_destroy_context(exa->cso);
}
- if (exa->ctx)
- exa->ctx->destroy(exa->ctx);
+ if (exa->pipe)
+ exa->pipe->destroy(exa->pipe);
exaDriverFini(pScrn->pScreen);
xfree(exa);
@@ -645,6 +804,12 @@ xorg_exa_init(ScrnInfoPtr pScrn)
pExa->pixmapOffsetAlign = 0;
pExa->pixmapPitchAlign = 1;
pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+#ifdef EXA_SUPPORTS_PREPARE_AUX
+ pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
+#endif
+#ifdef EXA_MIXED_PIXMAPS
+ pExa->flags |= EXA_MIXED_PIXMAPS;
+#endif
pExa->maxX = 8191; /* FIXME */
pExa->maxY = 8191; /* FIXME */
@@ -674,13 +839,15 @@ xorg_exa_init(ScrnInfoPtr pScrn)
}
exa->scrn = ms->screen;
- exa->ctx = ms->api->create_context(ms->api, exa->scrn);
+ exa->pipe = ms->api->create_context(ms->api, exa->scrn);
/* Share context with DRI */
- ms->ctx = exa->ctx;
+ ms->ctx = exa->pipe;
- exa->cso = cso_create_context(exa->ctx);
+ exa->cso = cso_create_context(exa->pipe);
exa->shaders = xorg_shaders_create(exa);
+ xorg_exa_init_state(exa);
+
return (void *)exa;
out_err:
@@ -698,3 +865,19 @@ exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
}
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence)
+{
+ exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
+}
+
+void xorg_exa_finish(struct exa_context *exa)
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
+
+ exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
+ exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
+}
+
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 5b515be139..d3f25ca844 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -14,7 +14,7 @@ struct xorg_shaders;
struct exa_context
{
ExaDriverPtr pExa;
- struct pipe_context *ctx;
+ struct pipe_context *pipe;
struct pipe_screen *scrn;
struct cso_context *cso;
struct xorg_shaders *shaders;
@@ -26,8 +26,17 @@ struct exa_context
int num_bound_samplers;
float solid_color[4];
-};
+ boolean has_solid_color;
+
+ struct {
+ struct exa_pixmap_priv *src;
+ struct exa_pixmap_priv *dst;
+ } copy;
+ /* we should combine these two */
+ float vertices2[4][2][4];
+ float vertices3[4][3][4];
+};
struct exa_pixmap_priv
{
@@ -36,15 +45,25 @@ struct exa_pixmap_priv
struct pipe_texture *tex;
struct pipe_texture *depth_stencil_tex;
- unsigned int color;
- struct pipe_surface *src_surf; /* for copies */
struct pipe_transfer *map_transfer;
unsigned map_count;
};
+#define XORG_FALLBACK(s, arg...) \
+do { \
+ if (ms->debug_fallback) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "fallback: " s "\n", ##arg); \
+ } \
+ return FALSE; \
+} while(0)
+
struct pipe_surface *
exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv);
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence);
+void xorg_exa_finish(struct exa_context *exa);
#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
index cfee10c3b3..bb5a42af37 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -52,8 +52,7 @@ struct xorg_shaders {
static const char over_op[] =
"SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
- "MUL TEMP[3], TEMP[0], TEMP[3]\n"
- "ADD TEMP[0], TEMP[3], TEMP[0]\n";
+ "MAD TEMP[3], TEMP[0], TEMP[3], TEMP[0]\n";
static INLINE void
@@ -79,8 +78,7 @@ vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
{
struct ureg_dst tmp = ureg_DECL_temporary(ureg);
struct ureg_src ret;
- ureg_MUL(ureg, tmp, coords, const0);
- ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
+ ureg_MAD(ureg, tmp, coords, const0, const1);
ret = ureg_src(tmp);
ureg_release_temporary(ureg, tmp);
return ret;
@@ -241,42 +239,39 @@ create_vs(struct pipe_context *pipe,
boolean is_fill = vs_traits & VS_FILL;
boolean is_composite = vs_traits & VS_COMPOSITE;
boolean has_mask = vs_traits & VS_MASK;
+ unsigned input_slot = 0;
ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
if (ureg == NULL)
return 0;
- const0 = ureg_DECL_constant(ureg);
- const1 = ureg_DECL_constant(ureg);
+ const0 = ureg_DECL_constant(ureg, 0);
+ const1 = ureg_DECL_constant(ureg, 1);
/* it has to be either a fill or a composite op */
debug_assert(is_fill ^ is_composite);
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_POSITION, 0);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
src = vs_normalize_coords(ureg, src,
const0, const1);
ureg_MOV(ureg, dst, src);
-
if (is_composite) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_GENERIC, 1);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
ureg_MOV(ureg, dst, src);
}
+
if (is_fill) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_COLOR, 1);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
ureg_MOV(ureg, dst, src);
}
if (has_mask) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_GENERIC, 2);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 2);
ureg_MOV(ureg, dst, src);
}
@@ -315,11 +310,11 @@ create_fs(struct pipe_context *pipe,
if (is_composite) {
src_sampler = ureg_DECL_sampler(ureg, 0);
src_input = ureg_DECL_fs_input(ureg,
- TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC,
0,
TGSI_INTERPOLATE_PERSPECTIVE);
- }
- if (is_fill) {
+ } else {
+ debug_assert(is_fill);
if (is_solid)
src_input = ureg_DECL_fs_input(ureg,
TGSI_SEMANTIC_COLOR,
@@ -335,7 +330,7 @@ create_fs(struct pipe_context *pipe,
if (has_mask) {
mask_sampler = ureg_DECL_sampler(ureg, 1);
mask_pos = ureg_DECL_fs_input(ureg,
- TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC,
1,
TGSI_INTERPOLATE_PERSPECTIVE);
}
@@ -370,11 +365,11 @@ create_fs(struct pipe_context *pipe,
else
src = out;
- coords = ureg_DECL_constant(ureg);
- const0124 = ureg_DECL_constant(ureg);
- matrow0 = ureg_DECL_constant(ureg);
- matrow1 = ureg_DECL_constant(ureg);
- matrow2 = ureg_DECL_constant(ureg);
+ coords = ureg_DECL_constant(ureg, 0);
+ const0124 = ureg_DECL_constant(ureg, 1);
+ matrow0 = ureg_DECL_constant(ureg, 2);
+ matrow1 = ureg_DECL_constant(ureg, 3);
+ matrow2 = ureg_DECL_constant(ureg, 4);
if (is_lingrad) {
linear_gradient(ureg, src,
@@ -470,12 +465,12 @@ struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
unsigned vs_traits,
unsigned fs_traits)
{
- struct xorg_shader shader = {0};
+ struct xorg_shader shader = { NULL, NULL };
void *vs, *fs;
- vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
+ vs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_VERTEX,
sc->vs_hash, vs_traits);
- fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
+ fs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_FRAGMENT,
sc->fs_hash, fs_traits);
debug_assert(vs && fs);
diff --git a/src/gallium/state_trackers/xorg/xorg_output.c b/src/gallium/state_trackers/xorg/xorg_output.c
index 950af942f5..26f45f8d64 100644
--- a/src/gallium/state_trackers/xorg/xorg_output.c
+++ b/src/gallium/state_trackers/xorg/xorg_output.c
@@ -42,8 +42,12 @@
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#endif
#include "X11/Xatom.h"
diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h
index b1ab783a15..db2f16f63e 100644
--- a/src/gallium/state_trackers/xorg/xorg_tracker.h
+++ b/src/gallium/state_trackers/xorg/xorg_tracker.h
@@ -94,6 +94,7 @@ typedef struct _modesettingRec
/* exa */
void *exa;
Bool noEvict;
+ Bool debug_fallback;
#ifdef DRM_MODE_FEATURE_DIRTYFB
DamagePtr damage;
@@ -151,5 +152,11 @@ crtc_cursor_destroy(xf86CrtcPtr crtc);
void
output_init(ScrnInfoPtr pScrn);
+/***********************************************************************
+ * xorg_xv.c
+ */
+void
+xorg_init_video(ScreenPtr pScreen);
+
#endif /* _XORG_TRACKER_H_ */
diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c
new file mode 100644
index 0000000000..88955d47fd
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_xv.c
@@ -0,0 +1,212 @@
+#include "xorg_tracker.h"
+
+#include <xf86xv.h>
+#include <X11/extensions/Xv.h>
+#include <fourcc.h>
+
+/*XXX get these from pipe's texture limits */
+#define IMAGE_MAX_WIDTH 2048
+#define IMAGE_MAX_HEIGHT 2048
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast;
+
+#define NUM_TEXTURED_ATTRIBUTES 2
+static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_FORMATS 3
+static XF86VideoFormatRec Formats[NUM_FORMATS] = {
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86VideoEncodingRec DummyEncoding[1] = {
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+ {1, 1}
+ }
+};
+
+#define NUM_IMAGES 2
+static XF86ImageRec Images[NUM_IMAGES] = {
+ XVIMAGE_UYVY,
+ XVIMAGE_YUY2,
+};
+
+struct xorg_xv_port_priv {
+ RegionRec clip;
+};
+
+
+static void
+stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+}
+
+static int
+set_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 value, pointer data)
+{
+ return 0;
+}
+
+static int
+get_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 * value, pointer data)
+{
+ return 0;
+}
+
+static void
+query_best_size(ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h, pointer data)
+{
+}
+
+static int
+put_image(ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char *buf,
+ short width, short height,
+ Bool sync, RegionPtr clipBoxes, pointer data,
+ DrawablePtr pDraw)
+{
+ return 0;
+}
+
+static int
+query_image_attributes(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+ return 0;
+}
+
+static struct xorg_xv_port_priv *
+port_priv_create(ScreenPtr pScreen)
+{
+ /*ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];*/
+ /*modesettingPtr ms = modesettingPTR(pScrn);*/
+ struct xorg_xv_port_priv *priv = NULL;
+
+ priv = calloc(1, sizeof(struct xorg_xv_port_priv));
+
+ if (!priv)
+ return NULL;
+
+ REGION_NULL(pScreen, &priv->clip);
+
+ return priv;
+}
+
+static XF86VideoAdaptorPtr
+xorg_setup_textured_adapter(ScreenPtr pScreen)
+{
+ /*ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];*/
+ /*modesettingPtr ms = modesettingPTR(pScrn);*/
+ XF86VideoAdaptorPtr adapt;
+ XF86AttributePtr attrs;
+ DevUnion *dev_unions;
+ int nports = 16, i;
+ int nattributes;
+
+ nattributes = NUM_TEXTURED_ATTRIBUTES;
+
+ adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
+ dev_unions = calloc(nports, sizeof(DevUnion));
+ attrs = calloc(nattributes, sizeof(XF86AttributeRec));
+ if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
+ free(adapt);
+ free(dev_unions);
+ free(attrs);
+ return NULL;
+ }
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = 0;
+ adapt->name = "Gallium3D Textured Video";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 0;
+ adapt->pPortPrivates = dev_unions;
+ adapt->nAttributes = nattributes;
+ adapt->pAttributes = attrs;
+ memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
+ adapt->nImages = NUM_IMAGES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = stop_video;
+ adapt->SetPortAttribute = set_port_attribute;
+ adapt->GetPortAttribute = get_port_attribute;
+ adapt->QueryBestSize = query_best_size;
+ adapt->PutImage = put_image;
+ adapt->QueryImageAttributes = query_image_attributes;
+
+ for (i = 0; i < nports; i++) {
+ struct xorg_xv_port_priv *priv =
+ port_priv_create(pScreen);
+
+ adapt->pPortPrivates[i].ptr = (pointer) (priv);
+ adapt->nPorts++;
+ }
+
+ return adapt;
+}
+
+void
+xorg_init_video(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ /*modesettingPtr ms = modesettingPTR(pScrn);*/
+ XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
+ XF86VideoAdaptorPtr textured_adapter;
+ int num_adaptors;
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+ new_adaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
+ if (new_adaptors == NULL)
+ return;
+
+ memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+ adaptors = new_adaptors;
+
+ /* Add the adaptors supported by our hardware. First, set up the atoms
+ * that will be used by both output adaptors.
+ */
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+
+ textured_adapter = xorg_setup_textured_adapter(pScreen);
+
+ debug_assert(textured_adapter);
+
+ if (textured_adapter) {
+ adaptors[num_adaptors++] = textured_adapter;
+ }
+
+ if (num_adaptors) {
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling Xv because no adaptors could be initialized.\n");
+ }
+
+ free(adaptors);
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/Makefile b/src/gallium/state_trackers/xorg/xvmc/Makefile
new file mode 100644
index 0000000000..126dc6d58f
--- /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/SConscript b/src/gallium/state_trackers/xorg/xvmc/SConscript
new file mode 100644
index 0000000000..cb25d68bd8
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/SConscript
@@ -0,0 +1,27 @@
+#######################################################################
+# SConscript for xvmc state_tracker
+
+Import('*')
+
+if 'xorg/xvmc' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/gallium/include',
+ '#/src/gallium/auxiliary',
+ '#/src/gallium/winsys/g3dvl',
+ ])
+
+ env.ParseConfig('pkg-config --cflags --libs xvmc')
+
+ st_xvmc = env.ConvenienceLibrary(
+ target = 'st_xvmc',
+ source = [ 'block.c',
+ 'surface.c',
+ 'context.c',
+ 'subpicture.c',
+ 'attributes.c',
+ ]
+ )
+ Export('st_xvmc')
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 0000000000..638da0b577
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/attributes.c
@@ -0,0 +1,19 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMClib.h>
+
+XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number)
+{
+ return NULL;
+}
+
+Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value)
+{
+ return BadImplementation;
+}
+
+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 0000000000..78fddfb79e
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/block.c
@@ -0,0 +1,61 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <util/u_memory.h>
+#include "xvmc_private.h"
+
+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;
+}
+
+Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks)
+{
+ assert(dpy);
+ assert(blocks);
+ FREE(blocks->blocks);
+
+ return Success;
+}
+
+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;
+}
+
+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 0000000000..6d90dfc367
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/context.c
@@ -0,0 +1,214 @@
+#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 <util/u_debug.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)
+{
+ 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);
+
+ *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;
+ *screen = i;
+ }
+
+ XFree(surface_info);
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+ }
+
+ if (!*found_port)
+ return XvBadPort;
+ if (!found_surface)
+ return BadMatch;
+ if (width > max_width || height > max_height)
+ return BadValue;
+ if (flags != XVMC_DIRECT && flags != 0)
+ 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);
+
+ 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);
+ }
+
+ return -1;
+}
+
+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;
+ Status ret;
+ struct pipe_screen *screen;
+ struct pipe_video_context *vpipe;
+ XvMCContextPrivate *context_priv;
+
+ 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);
+
+ /* Success and XvBadPort have the same value */
+ if (ret != Success || !found_port)
+ return ret;
+
+ /* XXX: Current limits */
+ if (chroma_format != XVMC_CHROMA_FORMAT_420) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Unsupported chroma format.\n");
+ return BadImplementation;
+ }
+ if (mc_type != (XVMC_MOCOMP | XVMC_MPEG_2)) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
+ return BadImplementation;
+ }
+ if (!(surface_flags & XVMC_INTRA_UNSIGNED)) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Signed intra unsupported.\n");
+ return BadImplementation;
+ }
+
+ context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
+ if (!context_priv)
+ return BadAlloc;
+
+ /* TODO: Reuse screen if process creates another context */
+ screen = vl_screen_create(dpy, scrn);
+
+ if (!screen) {
+ FREE(context_priv);
+ return BadAlloc;
+ }
+
+ vpipe = vl_video_create(screen, ProfileToPipe(mc_type),
+ FormatToPipe(chroma_format), width, height);
+
+ if (!vpipe) {
+ screen->destroy(screen);
+ FREE(context_priv);
+ return BadAlloc;
+ }
+
+ context_priv->vpipe = vpipe;
+
+ 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();
+
+ return Success;
+}
+
+Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
+{
+ struct pipe_screen *screen;
+ struct pipe_video_context *vpipe;
+ XvMCContextPrivate *context_priv;
+
+ assert(dpy);
+
+ if (!context || !context->privData)
+ return XvMCBadContext;
+
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+ pipe_surface_reference(&context_priv->backbuffer, NULL);
+ screen = vpipe->screen;
+ vpipe->destroy(vpipe);
+ screen->destroy(screen);
+ FREE(context_priv);
+ context->privData = NULL;
+
+ 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 0000000000..78ba618f5a
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
@@ -0,0 +1,168 @@
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMClib.h>
+
+Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
+ unsigned short width, unsigned short height, int xvimage_id)
+{
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+
+ assert(subpicture);
+
+ /*if (width > || height > )
+ return BadValue;*/
+
+ /*if (xvimage_id != )
+ return BadMatch;*/
+
+ 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 = 0;
+ subpicture->component_order[0] = 0;
+ subpicture->component_order[1] = 0;
+ subpicture->component_order[2] = 0;
+ subpicture->component_order[3] = 0;
+ /* TODO: subpicture->privData = ;*/
+
+ SyncHandle();
+
+ return Success;
+}
+
+Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
+ unsigned short width, unsigned short height, unsigned int color)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ /* TODO: Assert clear rect is within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
+ short srcx, short srcy, unsigned short width, unsigned short height,
+ short dstx, short dsty)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(image);
+
+ if (subpicture->xvimage_id != image->id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return BadImplementation;
+}
+
+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;
+}
+
+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)
+{
+ assert(dpy);
+
+ if (!target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (target_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+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;
+}
+
+Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+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 0000000000..6b7dbf11dc
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/surface.c
@@ -0,0 +1,382 @@
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_video_state.h>
+#include <pipe/p_state.h>
+#include <util/u_memory.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);
+
+ 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);
+ }
+
+ return -1;
+}
+
+static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
+{
+ switch (xvmc_motion_type) {
+ case XVMC_PREDICTION_FRAME:
+ return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ?
+ PIPE_MPEG12_MOTION_TYPE_16x8 : PIPE_MPEG12_MOTION_TYPE_FRAME;
+ case XVMC_PREDICTION_FIELD:
+ return PIPE_MPEG12_MOTION_TYPE_FIELD;
+ case XVMC_PREDICTION_DUAL_PRIME:
+ return PIPE_MPEG12_MOTION_TYPE_DUALPRIME;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static bool
+CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height,
+ struct pipe_surface **backbuffer)
+{
+ struct pipe_texture template;
+ struct pipe_texture *tex;
+
+ assert(vpipe);
+
+ if (*backbuffer) {
+ if ((*backbuffer)->width != width || (*backbuffer)->height != height)
+ pipe_surface_reference(backbuffer, NULL);
+ else
+ return true;
+ }
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ /* XXX: Needs to match the drawable's format? */
+ template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ template.last_level = 0;
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ tex = vpipe->screen->texture_create(vpipe->screen, &template);
+ if (!tex)
+ return false;
+
+ *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ pipe_texture_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->clear_surface(vpipe, 0, 0, width, height, 0, *backbuffer);
+
+ return true;
+}
+
+static void
+MacroBlocksToPipe(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_mb->dct_type);
+ /* 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->cbp = xvmc_mb->coded_block_pattern;
+ pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
+
+ ++pipe_macroblocks;
+ ++xvmc_mb;
+ }
+}
+
+Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
+{
+ XvMCContextPrivate *context_priv;
+ struct pipe_video_context *vpipe;
+ XvMCSurfacePrivate *surface_priv;
+ struct pipe_video_surface *vsfc;
+
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+ if (!surface)
+ return XvMCBadSurface;
+
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+
+ surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
+ if (!surface_priv)
+ return BadAlloc;
+
+ vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
+ vpipe->width, vpipe->height);
+ 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();
+
+ return Success;
+}
+
+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];
+
+ 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->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(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);
+
+ return Success;
+}
+
+Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ return Success;
+}
+
+Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ return Success;
+}
+
+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)
+{
+ Window root;
+ int x, y;
+ unsigned int width, height;
+ unsigned int border_width;
+ unsigned int depth;
+ struct pipe_video_context *vpipe;
+ XvMCSurfacePrivate *surface_priv;
+ XvMCContextPrivate *context_priv;
+ XvMCContext *context;
+ struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
+ struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
+
+ assert(dpy);
+
+ if (!surface || !surface->privData)
+ return XvMCBadSurface;
+
+ if (XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+ 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 < width);
+ assert(desty + desth - 1 < height);
+ */
+
+ surface_priv = surface->privData;
+ context = surface_priv->context;
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+
+ if (!CreateOrResizeBackBuffer(vpipe, width, height, &context_priv->backbuffer))
+ return BadAlloc;
+
+ vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
+ context_priv->backbuffer, &dst_rect, surface_priv->disp_fence);
+
+ vl_video_bind_drawable(vpipe, drawable);
+
+ vpipe->screen->flush_frontbuffer
+ (
+ vpipe->screen,
+ context_priv->backbuffer,
+ vpipe->priv
+ );
+
+ return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ assert(status);
+
+ *status = 0;
+
+ return Success;
+}
+
+Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
+{
+ XvMCSurfacePrivate *surface_priv;
+
+ assert(dpy);
+
+ if (!surface || !surface->privData)
+ return XvMCBadSurface;
+
+ surface_priv = surface->privData;
+ pipe_video_surface_reference(&surface_priv->pipe_vsfc, NULL);
+ FREE(surface_priv);
+ surface->privData = NULL;
+
+ return Success;
+}
+
+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 0000000000..e1d2f9023d
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore
@@ -0,0 +1,5 @@
+test_context
+test_surface
+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 0000000000..c875dd7605
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile
@@ -0,0 +1,28 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBS = -lXvMCW -lXvMC -lXv -lX11
+
+#############################################
+
+.PHONY: default clean
+
+default: test_context test_surface 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_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_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 0000000000..dc80adfa65
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c
@@ -0,0 +1,84 @@
+#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, &macroblocks) == XvMCBadContext);
+ /* Test 0 macroblocks */
+ assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == 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, &macroblocks) == 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 0000000000..53f7449cd0
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c
@@ -0,0 +1,92 @@
+#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 0000000000..6d720dfcdc
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c
@@ -0,0 +1,290 @@
+#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_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c
new file mode 100644
index 0000000000..06948201ac
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c
@@ -0,0 +1,71 @@
+#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 0000000000..59a03ca813
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c
@@ -0,0 +1,119 @@
+#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 0000000000..af71ad74e1
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h
@@ -0,0 +1,42 @@
+#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 0000000000..97adcfc58a
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c
@@ -0,0 +1,273 @@
+#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 0000000000..1e3dd561c6
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
@@ -0,0 +1,31 @@
+#ifndef xvmc_private_h
+#define xvmc_private_h
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+#define BLOCK_SIZE_SAMPLES 64
+#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2)
+
+struct pipe_video_context;
+struct pipe_surface;
+struct pipe_fence_handle;
+
+typedef struct
+{
+ struct pipe_video_context *vpipe;
+ struct pipe_surface *backbuffer;
+} XvMCContextPrivate;
+
+typedef struct
+{
+ struct pipe_video_surface *pipe_vsfc;
+ struct pipe_fence_handle *render_fence;
+ struct pipe_fence_handle *disp_fence;
+
+ /* Some XvMC functions take a surface but not a context,
+ so we keep track of which context each surface belongs to. */
+ XvMCContext *context;
+} XvMCSurfacePrivate;
+
+#endif /* xvmc_private_h */