diff options
Diffstat (limited to 'src/mesa/drivers/dri/radeon')
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_context.h | 15 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_ioctl.c | 252 |
2 files changed, 238 insertions, 29 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h index 2efabd1f55..2015e96a74 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_context.h @@ -435,8 +435,23 @@ struct r100_context { GLuint c_textureBytes; GLuint c_vertexBuffers; + struct { + struct gl_fragment_program *bitmap_fp; + struct gl_vertex_program *passthrough_vp; + + struct gl_fragment_program *saved_fp; + GLboolean saved_fp_enable; + struct gl_vertex_program *saved_vp; + GLboolean saved_vp_enable; + + GLint saved_vp_x, saved_vp_y; + GLsizei saved_vp_width, saved_vp_height; + GLenum saved_matrix_mode; + } meta; + }; + #define R100_CONTEXT(ctx) ((r100ContextPtr)(ctx->DriverCtx)) diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c index 6a24fc45ae..22584f4817 100644 --- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c +++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c @@ -37,6 +37,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <sched.h> #include <errno.h> +#include "main/attrib.h" +#include "main/enable.h" +#include "main/blend.h" +#include "main/bufferobj.h" +#include "main/buffers.h" +#include "main/depth.h" +#include "main/shaders.h" +#include "main/texstate.h" +#include "main/varray.h" +#include "glapi/dispatch.h" +#include "swrast/swrast.h" +#include "main/stencil.h" +#include "main/matrix.h" + #include "main/glheader.h" #include "main/imports.h" #include "main/simple_list.h" @@ -405,42 +419,221 @@ void radeonEmitAOS( r100ContextPtr rmesa, */ #define RADEON_MAX_CLEARS 256 -static void radeonUserClear(GLcontext *ctx, GLuint flags) + + +static void +r100_meta_set_passthrough_transform(r100ContextPtr r100) { - GLuint mask = 0; + GLcontext *ctx = r100->radeon.glCtx; - if (flags & RADEON_FRONT) - mask |= BUFFER_BIT_FRONT_LEFT; + r100->meta.saved_vp_x = ctx->Viewport.X; + r100->meta.saved_vp_y = ctx->Viewport.Y; + r100->meta.saved_vp_width = ctx->Viewport.Width; + r100->meta.saved_vp_height = ctx->Viewport.Height; + r100->meta.saved_matrix_mode = ctx->Transform.MatrixMode; - if (flags & RADEON_BACK) - mask |= BUFFER_BIT_BACK_LEFT; + _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); - if (flags & RADEON_DEPTH) - mask |= BUFFER_BIT_DEPTH; + _mesa_MatrixMode(GL_PROJECTION); + _mesa_PushMatrix(); + _mesa_LoadIdentity(); + _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1); - if (flags & RADEON_STENCIL) - mask |= BUFFER_BIT_STENCIL; + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_PushMatrix(); + _mesa_LoadIdentity(); +} -#if 1 - _swrast_Clear(ctx, mask); -#else - for ( i = 0 ; i < dPriv->numClipRects ; ) { +static void +r100_meta_restore_transform(r100ContextPtr r100) +{ + _mesa_MatrixMode(GL_PROJECTION); + _mesa_PopMatrix(); + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_PopMatrix(); - } + _mesa_MatrixMode(r100->meta.saved_matrix_mode); - if (flags & (RADEON_FRONT | RADEON_BACK)) { - OUT_BATCH(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_BATCH((RADEON_WAIT_3D_IDLECLEAN | - RADEON_WAIT_HOST_IDLECLEAN)); - OUT_BATCH_REGVAL(RADEON_DP_WRITE_MASK, 0); //clear->color_mask); + _mesa_Viewport(r100->meta.saved_vp_x, r100->meta.saved_vp_y, + r100->meta.saved_vp_width, r100->meta.saved_vp_height); +} +/** + * Perform glClear where mask contains only color, depth, and/or stencil. + * + * The implementation is based on calling into Mesa to set GL state and + * performing normal triangle rendering. The intent of this path is to + * have as generic a path as possible, so that any driver could make use of + * it. + */ +static void radeon_clear_tris(GLcontext *ctx, GLbitfield mask) +{ + r100ContextPtr rmesa = R100_CONTEXT(ctx); + GLfloat vertices[4][3]; + GLfloat color[4][4]; + GLfloat dst_z; + struct gl_framebuffer *fb = ctx->DrawBuffer; + int i; + GLboolean saved_fp_enable = GL_FALSE, saved_vp_enable = GL_FALSE; + GLboolean saved_shader_program = 0; + unsigned int saved_active_texture; + + assert((mask & ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT | + BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) == 0); + + _mesa_PushAttrib(GL_COLOR_BUFFER_BIT | + GL_CURRENT_BIT | + GL_DEPTH_BUFFER_BIT | + GL_ENABLE_BIT | + GL_STENCIL_BUFFER_BIT | + GL_TRANSFORM_BIT | + GL_CURRENT_BIT); + _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + saved_active_texture = ctx->Texture.CurrentUnit; + + /* Disable existing GL state we don't want to apply to a clear. */ + _mesa_Disable(GL_ALPHA_TEST); + _mesa_Disable(GL_BLEND); + _mesa_Disable(GL_CULL_FACE); + _mesa_Disable(GL_FOG); + _mesa_Disable(GL_POLYGON_SMOOTH); + _mesa_Disable(GL_POLYGON_STIPPLE); + _mesa_Disable(GL_POLYGON_OFFSET_FILL); + _mesa_Disable(GL_LIGHTING); + _mesa_Disable(GL_CLIP_PLANE0); + _mesa_Disable(GL_CLIP_PLANE1); + _mesa_Disable(GL_CLIP_PLANE2); + _mesa_Disable(GL_CLIP_PLANE3); + _mesa_Disable(GL_CLIP_PLANE4); + _mesa_Disable(GL_CLIP_PLANE5); + if (ctx->Extensions.ARB_fragment_program && ctx->FragmentProgram.Enabled) { + saved_fp_enable = GL_TRUE; + _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB); + } + if (ctx->Extensions.ARB_vertex_program && ctx->VertexProgram.Enabled) { + saved_vp_enable = GL_TRUE; + _mesa_Disable(GL_VERTEX_PROGRAM_ARB); + } + if (ctx->Extensions.ARB_shader_objects && ctx->Shader.CurrentProgram) { + saved_shader_program = ctx->Shader.CurrentProgram->Name; + _mesa_UseProgramObjectARB(0); + } + + if (ctx->Texture._EnabledUnits != 0) { + int i; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + _mesa_ActiveTextureARB(GL_TEXTURE0 + i); + _mesa_Disable(GL_TEXTURE_1D); + _mesa_Disable(GL_TEXTURE_2D); + _mesa_Disable(GL_TEXTURE_3D); + if (ctx->Extensions.ARB_texture_cube_map) + _mesa_Disable(GL_TEXTURE_CUBE_MAP_ARB); + if (ctx->Extensions.NV_texture_rectangle) + _mesa_Disable(GL_TEXTURE_RECTANGLE_NV); + if (ctx->Extensions.MESA_texture_array) { + _mesa_Disable(GL_TEXTURE_1D_ARRAY_EXT); + _mesa_Disable(GL_TEXTURE_2D_ARRAY_EXT); + } + } } - - if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) - && (flags & RADEON_CLEAR_FASTZ)) { + + r100_meta_set_passthrough_transform(rmesa); + + for (i = 0; i < 4; i++) { + color[i][0] = ctx->Color.ClearColor[0]; + color[i][1] = ctx->Color.ClearColor[1]; + color[i][2] = ctx->Color.ClearColor[2]; + color[i][3] = ctx->Color.ClearColor[3]; + } + + /* convert clear Z from [0,1] to NDC coord in [-1,1] */ + dst_z = -1.0 + 2.0 * ctx->Depth.Clear; + + /* Prepare the vertices, which are the same regardless of which buffer we're + * drawing to. + */ + vertices[0][0] = fb->_Xmin; + vertices[0][1] = fb->_Ymin; + vertices[0][2] = dst_z; + vertices[1][0] = fb->_Xmax; + vertices[1][1] = fb->_Ymin; + vertices[1][2] = dst_z; + vertices[2][0] = fb->_Xmax; + vertices[2][1] = fb->_Ymax; + vertices[2][2] = dst_z; + vertices[3][0] = fb->_Xmin; + vertices[3][1] = fb->_Ymax; + vertices[3][2] = dst_z; + + _mesa_ColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &color); + _mesa_VertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), &vertices); + _mesa_Enable(GL_COLOR_ARRAY); + _mesa_Enable(GL_VERTEX_ARRAY); + + while (mask != 0) { + GLuint this_mask = 0; + + if (mask & BUFFER_BIT_BACK_LEFT) + this_mask = BUFFER_BIT_BACK_LEFT; + else if (mask & BUFFER_BIT_FRONT_LEFT) + this_mask = BUFFER_BIT_FRONT_LEFT; + + /* Clear depth/stencil in the same pass as color. */ + this_mask |= (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)); + + /* Select the current color buffer and use the color write mask if + * we have one, otherwise don't write any color channels. + */ + if (this_mask & BUFFER_BIT_FRONT_LEFT) + _mesa_DrawBuffer(GL_FRONT_LEFT); + else if (this_mask & BUFFER_BIT_BACK_LEFT) + _mesa_DrawBuffer(GL_BACK_LEFT); + else + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* Control writing of the depth clear value to depth. */ + if (this_mask & BUFFER_BIT_DEPTH) { + _mesa_DepthFunc(GL_ALWAYS); + _mesa_Enable(GL_DEPTH_TEST); + } else { + _mesa_Disable(GL_DEPTH_TEST); + _mesa_DepthMask(GL_FALSE); + } + + /* Control writing of the stencil clear value to stencil. */ + if (this_mask & BUFFER_BIT_STENCIL) { + _mesa_Enable(GL_STENCIL_TEST); + _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + _mesa_StencilFuncSeparate(GL_FRONT, GL_ALWAYS, ctx->Stencil.Clear, + ctx->Stencil.WriteMask[0]); + } else { + _mesa_Disable(GL_STENCIL_TEST); + } + + CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); + mask &= ~this_mask; } -#endif + + r100_meta_restore_transform(rmesa); + + _mesa_ActiveTextureARB(GL_TEXTURE0 + saved_active_texture); + if (saved_fp_enable) + _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB); + if (saved_vp_enable) + _mesa_Enable(GL_VERTEX_PROGRAM_ARB); + + if (saved_shader_program) + _mesa_UseProgramObjectARB(saved_shader_program); + + _mesa_PopClientAttrib(); + _mesa_PopAttrib(); +} + +static void radeonUserClear(GLcontext *ctx, GLuint mask) +{ + radeon_clear_tris(ctx, mask); } static void radeonKernelClear(GLcontext *ctx, GLuint flags) @@ -570,6 +763,7 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask ) __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; GLuint flags = 0; GLuint color_mask = 0; + GLuint orig_mask = mask; if ( RADEON_DEBUG & DEBUG_IOCTL ) { fprintf( stderr, "radeonClear\n"); @@ -582,7 +776,7 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask ) return; } - radeonFlush( ctx ); + radeon_firevertices(&rmesa->radeon); if ( mask & BUFFER_BIT_FRONT_LEFT ) { flags |= RADEON_FRONT; @@ -627,11 +821,11 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask ) } if (rmesa->radeon.radeonScreen->kernel_mm) - radeonUserClear(ctx, flags); - else + radeonUserClear(ctx, orig_mask); + else { radeonKernelClear(ctx, flags); - - rmesa->radeon.hw.all_dirty = GL_TRUE; + rmesa->radeon.hw.all_dirty = GL_TRUE; + } } void radeonInitIoctlFuncs( GLcontext *ctx ) |