diff options
-rw-r--r-- | progs/demos/dissolve.c | 137 | ||||
-rw-r--r-- | progs/glsl/SConscript | 2 | ||||
-rw-r--r-- | progs/glsl/vsraytrace.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_screen.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_sampler.c | 8 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_fence.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_fence.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_flush.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 53 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 1 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/dri_st_api.c | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm_glsl.c | 14 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r200/r200_state.c | 7 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/r300_state.c | 7 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r600/r700_state.c | 7 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_state.c | 7 |
18 files changed, 244 insertions, 54 deletions
diff --git a/progs/demos/dissolve.c b/progs/demos/dissolve.c index 0b8df1bb66..8ab5242d91 100644 --- a/progs/demos/dissolve.c +++ b/progs/demos/dissolve.c @@ -1,5 +1,5 @@ /** - * Dissolve between two images using randomized stencil buffer + * Dissolve between two images using randomized/patterned stencil buffer * and varying stencil ref. * * Brian Paul @@ -9,6 +9,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <math.h> #include <GL/glut.h> #include "readtex.h" @@ -28,6 +29,8 @@ static GLfloat ScaleX[2], ScaleY[2]; static GLubyte StencilRef = 0; +static int Mode = 0; + static void Idle(void) @@ -38,13 +41,114 @@ Idle(void) static void -RandomizeStencilBuffer(void) +FillRandomPixels(GLubyte *b) { - GLubyte *b = malloc(WinWidth * WinHeight); int i; for (i = 0; i < WinWidth * WinHeight; i++) { b[i] = rand() & 0xff; } +} + + +static void +FillRandomRects(GLubyte *b) +{ + int i; + + memset(b, 0, WinWidth * WinHeight); + + for (i = 0; i < 256; i++) { + int x = rand() % WinWidth; + int y = rand() % WinHeight; + int w = rand() % 60; + int h = rand() % 60; + int ix, iy; + + if (x + w > WinWidth) + w = WinWidth - x; + if (y + h > WinHeight) + h = WinHeight - y; + + for (iy = 0; iy < h; iy++) { + for (ix = 0; ix < w; ix++) { + int p = (y + iy) * WinWidth + x + ix; + b[p] = i; + } + } + } +} + + +static void +FillWipe(GLubyte *b) +{ + int iy, ix; + + memset(b, 0, WinWidth * WinHeight); + + for (iy = 0; iy < WinHeight; iy++) { + for (ix = 0; ix < WinWidth; ix++) { + int p = iy * WinWidth + ix; + b[p] = 2 * ix + iy / 2; + } + } +} + + +static void +FillMoire(GLubyte *b) +{ + int iy, ix; + + memset(b, 0, WinWidth * WinHeight); + + for (iy = 0; iy < WinHeight; iy++) { + for (ix = 0; ix < WinWidth; ix++) { + int p = iy * WinWidth + ix; + b[p] = (ix / 2) * (ix / 2) - (iy / 2) * (iy / 2); + } + } +} + + +static void +FillWaves(GLubyte *b) +{ + int iy, ix; + + memset(b, 0, WinWidth * WinHeight); + + for (iy = 0; iy < WinHeight; iy++) { + for (ix = 0; ix < WinWidth; ix++) { + int p = iy * WinWidth + ix; + float x = 8.0 * 3.1415 * ix / (float) WinWidth; + b[p] = (int) (25.0 * sin(x) ) - iy*2; + } + } +} + + +typedef void (*FillFunc)(GLubyte *b); + + +static FillFunc Funcs[] = { + FillRandomPixels, + FillRandomRects, + FillWipe, + FillMoire, + FillWaves +}; + +#define NUM_MODES (sizeof(Funcs) / sizeof(Funcs[0])) + + + +static void +InitStencilBuffer(void) +{ + GLubyte *b = malloc(WinWidth * WinHeight); + + Funcs[Mode](b); glStencilFunc(GL_ALWAYS, 0, ~0); glPixelZoom(1.0, 1.0); @@ -54,7 +158,6 @@ RandomizeStencilBuffer(void) } - static void Draw(void) { @@ -85,7 +188,7 @@ Reshape(int width, int height) glLoadIdentity(); glTranslatef(0.0, 0.0, -15.0); - RandomizeStencilBuffer(); + InitStencilBuffer(); ScaleX[0] = (float) width / ImgWidth[0]; ScaleY[0] = (float) height / ImgHeight[0]; @@ -102,12 +205,26 @@ Key(unsigned char key, int x, int y) (void) y; switch (key) { case 'a': + case ' ': Anim = !Anim; if (Anim) glutIdleFunc(Idle); else glutIdleFunc(NULL); break; + case 'i': + InitStencilBuffer(); + break; + case '-': + StencilRef--; + break; + case '+': + StencilRef++; + break; + case 'm': + Mode = (Mode + 1) % NUM_MODES; + InitStencilBuffer(); + break; case 27: glutDestroyWindow(Win); exit(0); @@ -143,8 +260,8 @@ Init(void) int main(int argc, char *argv[]) { - glutInit(&argc, argv); glutInitWindowSize(WinWidth, WinHeight); + glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); Win = glutCreateWindow(argv[0]); glutReshapeFunc(Reshape); @@ -153,6 +270,14 @@ main(int argc, char *argv[]) if (Anim) glutIdleFunc(Idle); Init(); + + printf("Keys:\n"); + printf(" a/SPACE toggle animation\n"); + printf(" +/- single step\n"); + printf(" i re-init pattern\n"); + printf(" m change pattern/dissolve mode\n"); + printf(" ESC exit\n"); + glutMainLoop(); return 0; } diff --git a/progs/glsl/SConscript b/progs/glsl/SConscript index 8f2ebcf69c..02884e5a71 100644 --- a/progs/glsl/SConscript +++ b/progs/glsl/SConscript @@ -8,6 +8,7 @@ progs = [ 'convolutions', 'deriv', 'fragcoord', + 'fsraytrace', 'identity', 'linktest', 'mandelbrot', @@ -27,6 +28,7 @@ progs = [ 'twoside', 'vert-or-frag-only', 'vert-tex', + 'vsraytrace', ] for prog in progs: diff --git a/progs/glsl/vsraytrace.c b/progs/glsl/vsraytrace.c index d7726c787b..962b1bdb4c 100644 --- a/progs/glsl/vsraytrace.c +++ b/progs/glsl/vsraytrace.c @@ -202,7 +202,7 @@ static const char* vsSource = "void main() \n" "{ \n" " const vec3 cameraPos = vec3(0,0,3); \n" - " const vec3 rayDir = normalize(vec3(gl_Vertex.x, gl_Vertex.y, -1.0) * rot);\n" + " vec3 rayDir = normalize(vec3(gl_Vertex.x, gl_Vertex.y, -1.0) * rot);\n" " Ray ray = Ray(cameraPos, rayDir); \n" " gl_Position = gl_Vertex; \n" " gl_FrontColor = trace1(ray); \n" diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index e5bf4a20bd..48a39edad2 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -165,8 +165,12 @@ i915_is_format_supported(struct pipe_screen *screen, unsigned geom_flags) { static const enum pipe_format tex_supported[] = { - PIPE_FORMAT_A8B8G8R8_UNORM, PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM, +#if 0 + PIPE_FORMAT_R8G8B8X8_UNORM, +#endif PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_L8_UNORM, PIPE_FORMAT_A8_UNORM, diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index d6da822549..4c326561cb 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -192,6 +192,14 @@ translate_texture_format(enum pipe_format pipeFormat) return MAPSURF_16BIT | MT_16BIT_ARGB4444; case PIPE_FORMAT_B8G8R8A8_UNORM: return MAPSURF_32BIT | MT_32BIT_ARGB8888; + case PIPE_FORMAT_B8G8R8X8_UNORM: + return MAPSURF_32BIT | MT_32BIT_XRGB8888; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return MAPSURF_32BIT | MT_32BIT_ABGR8888; +#if 0 + case PIPE_FORMAT_R8G8B8X8_UNORM: + return MAPSURF_32BIT | MT_32BIT_XBGR8888; +#endif case PIPE_FORMAT_YUYV: return (MAPSURF_422 | MT_422_YCRCB_NORMAL); case PIPE_FORMAT_UYVY: diff --git a/src/gallium/drivers/llvmpipe/lp_fence.c b/src/gallium/drivers/llvmpipe/lp_fence.c index 525c117f31..00dc3eab6b 100644 --- a/src/gallium/drivers/llvmpipe/lp_fence.c +++ b/src/gallium/drivers/llvmpipe/lp_fence.c @@ -29,6 +29,7 @@ #include "pipe/p_screen.h" #include "util/u_memory.h" #include "util/u_inlines.h" +#include "lp_debug.h" #include "lp_fence.h" @@ -99,6 +100,21 @@ llvmpipe_fence_finish(struct pipe_screen *screen, } +void +lp_fence_signal(struct lp_fence *fence) +{ + pipe_mutex_lock(fence->mutex); + + fence->count++; + assert(fence->count <= fence->rank); + + LP_DBG(DEBUG_RAST, "%s count=%u rank=%u\n", __FUNCTION__, + fence->count, fence->rank); + + pipe_condvar_signal(fence->signalled); + + pipe_mutex_unlock(fence->mutex); +} void diff --git a/src/gallium/drivers/llvmpipe/lp_fence.h b/src/gallium/drivers/llvmpipe/lp_fence.h index c90e6de423..d9270f5784 100644 --- a/src/gallium/drivers/llvmpipe/lp_fence.h +++ b/src/gallium/drivers/llvmpipe/lp_fence.h @@ -54,6 +54,10 @@ lp_fence_create(unsigned rank); void +lp_fence_signal(struct lp_fence *fence); + + +void llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen); diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index 636d72a9bb..782669a1e7 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -111,7 +111,6 @@ llvmpipe_flush_texture(struct pipe_context *pipe, boolean cpu_access, boolean do_not_flush) { - struct pipe_fence_handle *last_fence = NULL; unsigned referenced; referenced = pipe->is_texture_referenced(pipe, texture, face, level); @@ -142,7 +141,7 @@ llvmpipe_flush_texture(struct pipe_context *pipe, pipe->flush(pipe, flush_flags, &fence); - if (last_fence) { + if (fence) { pipe->screen->fence_finish(pipe->screen, fence, 0); pipe->screen->fence_reference(pipe->screen, &fence, NULL); } diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 3a51800c40..cd9919ca90 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -491,18 +491,7 @@ lp_rast_fence(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { struct lp_fence *fence = arg.fence; - - pipe_mutex_lock( fence->mutex ); - - fence->count++; - assert(fence->count <= fence->rank); - - LP_DBG(DEBUG_RAST, "%s count=%u rank=%u\n", __FUNCTION__, - fence->count, fence->rank); - - pipe_condvar_signal( fence->signalled ); - - pipe_mutex_unlock( fence->mutex ); + lp_fence_signal(fence); } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index fbb0d6f8a6..4eeb98621f 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -318,16 +318,30 @@ lp_setup_fence( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ - struct lp_fence *fence = lp_fence_create(rank); + struct lp_fence *fence; LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); - set_scene_state( setup, SETUP_ACTIVE ); + if (setup->state == SETUP_FLUSHED) { + /* We're in a flushed state so there's nothing in the bins. + * No need to wait on a fence. + */ + fence = NULL; + } + else { + /* There's material in the bins. Emit the fence into the bins. + * When the rasterizer(s) find the fence, they'll signal on it. + */ + fence = lp_fence_create(rank); - /* insert the fence into all command bins */ - lp_scene_bin_everywhere( scene, - lp_rast_fence, - lp_rast_arg_fence(fence) ); + set_scene_state( setup, SETUP_ACTIVE ); + + /* insert the fence into all command bins */ + lp_scene_bin_everywhere( scene, + lp_rast_fence, + lp_rast_arg_fence(fence) ); + + } return (struct pipe_fence_handle *) fence; } @@ -489,6 +503,12 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->height = tex->height0; jit_tex->depth = tex->depth0; jit_tex->last_level = tex->last_level; + + /* We're referencing the texture's internal data, so save a + * reference to it. + */ + pipe_texture_reference(&setup->fs.current_tex[i], tex); + if (!lp_tex->dt) { /* regular texture - setup array of mipmap level pointers */ int j; @@ -511,12 +531,6 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->row_stride[0] = lp_tex->stride[0]; assert(jit_tex->data[0]); } - - /* the scene references this texture */ - { - struct lp_scene *scene = lp_setup_get_current_scene(setup); - lp_scene_texture_reference(scene, tex); - } } } @@ -651,6 +665,7 @@ lp_setup_update_state( struct lp_setup_context *setup ) * the new, current state. So allocate a new lp_rast_state object * and append it to the bin's setup data buffer. */ + uint i; struct lp_rast_state *stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); if(stored) { @@ -664,6 +679,14 @@ lp_setup_update_state( struct lp_setup_context *setup ) lp_rast_set_state, lp_rast_arg_state(setup->fs.stored) ); } + + /* The scene now references the textures in the rasterization + * state record. Note that now. + */ + for (i = 0; i < Elements(setup->fs.current_tex); i++) { + if (setup->fs.current_tex[i]) + lp_scene_texture_reference(scene, setup->fs.current_tex[i]); + } } } @@ -679,8 +702,14 @@ lp_setup_update_state( struct lp_setup_context *setup ) void lp_setup_destroy( struct lp_setup_context *setup ) { + uint i; + reset_context( setup ); + for (i = 0; i < Elements(setup->fs.current_tex); i++) { + pipe_texture_reference(&setup->fs.current_tex[i], NULL); + } + pipe_buffer_reference(&setup->constants.current, NULL); /* free the scenes in the 'empty' queue */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 464fb36984..ca0dafab62 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -111,6 +111,7 @@ struct lp_setup_context const struct lp_rast_state *stored; /**< what's in the scene */ struct lp_rast_state current; /**< currently set state */ + struct pipe_texture *current_tex[PIPE_MAX_SAMPLERS]; } fs; /** fragment shader constants */ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 2bec946fe8..4433dcff21 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -35,7 +35,6 @@ #include "r300_screen.h" #include "r300_screen_buffer.h" #include "r300_state_invariant.h" -#include "r300_texture.h" #include "r300_transfer.h" #include "r300_winsys.h" diff --git a/src/gallium/state_trackers/dri/dri_st_api.c b/src/gallium/state_trackers/dri/dri_st_api.c index 2cde01967d..263c1e19a7 100644 --- a/src/gallium/state_trackers/dri/dri_st_api.c +++ b/src/gallium/state_trackers/dri/dri_st_api.c @@ -168,13 +168,18 @@ dri_drawable_get_buffers(struct dri_drawable *drawable, boolean with_format; __DRIbuffer *buffers; int num_buffers; - unsigned attachments[8]; + unsigned attachments[10]; unsigned num_attachments, i; assert(loader); with_format = (loader->base.version > 2 && loader->getBuffersWithFormat); num_attachments = 0; + + /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ + if (!with_format) + attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; + for (i = 0; i < *count; i++) { enum pipe_format format; int att; @@ -185,6 +190,9 @@ dri_drawable_get_buffers(struct dri_drawable *drawable, switch (statts[i]) { case ST_ATTACHMENT_FRONT_LEFT: + /* already added */ + if (!with_format) + continue; att = __DRI_BUFFER_FRONT_LEFT; break; case ST_ATTACHMENT_BACK_LEFT: diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index d78fb4ed09..3b7e421b16 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -583,11 +583,21 @@ static struct brw_reg get_src_reg(struct brw_wm_compile *c, if (component == SWIZZLE_ZERO) { return brw_imm_f(0.0F); } else if (component == SWIZZLE_ONE) { - return brw_imm_f(1.0F); + if (src->Negate) + return brw_imm_f(-1.0F); + else + return brw_imm_f(1.0F); } if (src->File == PROGRAM_CONSTANT) { - return brw_imm_f(params->ParameterValues[src->Index][component]); + float f = params->ParameterValues[src->Index][component]; + + if (src->Abs) + f = fabs(f); + if (src->Negate) + f = -f; + + return brw_imm_f(f); } } diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index 9c2ac05ad6..29d7bed8b6 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -2496,11 +2496,10 @@ void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *func functions->DrawBuffer = radeonDrawBuffer; functions->ReadBuffer = radeonReadBuffer; - if (radeon->radeonScreen->kernel_mm) { - functions->CopyPixels = _mesa_meta_CopyPixels; - functions->DrawPixels = _mesa_meta_DrawPixels; + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + if (radeon->radeonScreen->kernel_mm) functions->ReadPixels = radeonReadPixels; - } functions->AlphaFunc = r200AlphaFunc; functions->BlendColor = r200BlendColor; diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 749a2464e7..e660b1fb3b 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -2396,11 +2396,10 @@ void r300InitStateFuncs(radeonContextPtr radeon, struct dd_function_table *funct functions->DrawBuffer = radeonDrawBuffer; functions->ReadBuffer = radeonReadBuffer; - if (radeon->radeonScreen->kernel_mm) { - functions->CopyPixels = _mesa_meta_CopyPixels; - functions->DrawPixels = _mesa_meta_DrawPixels; + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + if (radeon->radeonScreen->kernel_mm) functions->ReadPixels = radeonReadPixels; - } } void r300InitShaderFunctions(r300ContextPtr r300) diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c index 1ff233d91e..1da31e7b2b 100644 --- a/src/mesa/drivers/dri/r600/r700_state.c +++ b/src/mesa/drivers/dri/r600/r700_state.c @@ -1861,10 +1861,9 @@ void r700InitStateFuncs(radeonContextPtr radeon, struct dd_function_table *funct functions->DrawBuffer = radeonDrawBuffer; functions->ReadBuffer = radeonReadBuffer; - if (radeon->radeonScreen->kernel_mm) { - functions->CopyPixels = _mesa_meta_CopyPixels; - functions->DrawPixels = _mesa_meta_DrawPixels; + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + if (radeon->radeonScreen->kernel_mm) functions->ReadPixels = radeonReadPixels; - } } diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index 0afbc19c12..539b067742 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -2249,11 +2249,10 @@ void radeonInitStateFuncs( GLcontext *ctx , GLboolean dri2 ) ctx->Driver.DrawBuffer = radeonDrawBuffer; ctx->Driver.ReadBuffer = radeonReadBuffer; - if (dri2) { - ctx->Driver.CopyPixels = _mesa_meta_CopyPixels; - ctx->Driver.DrawPixels = _mesa_meta_DrawPixels; + ctx->Driver.CopyPixels = _mesa_meta_CopyPixels; + ctx->Driver.DrawPixels = _mesa_meta_DrawPixels; + if (dri2) ctx->Driver.ReadPixels = radeonReadPixels; - } ctx->Driver.AlphaFunc = radeonAlphaFunc; ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate; |