radeon/r200/r300: fix missing dma buffer validation
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_state.c
index 1d683e5b3aae5892a4c27c38d52f1956cc71a634..28eea444377f9963e639d755b9f0d89dd81c5a4e 100644 (file)
@@ -47,6 +47,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "swrast_setup/swrast_setup.h"
 
 #include "radeon_context.h"
+#include "radeon_mipmap_tree.h"
 #include "radeon_ioctl.h"
 #include "radeon_state.h"
 #include "radeon_tcl.h"
@@ -406,23 +407,6 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
    }
 }
 
-
-/* =============================================================
- * Scissoring
- */
-static void radeonScissor( GLcontext *ctx,
-                          GLint x, GLint y, GLsizei w, GLsizei h )
-{
-   r100ContextPtr rmesa = R100_CONTEXT(ctx);
-
-   if ( ctx->Scissor.Enabled ) {
-      RADEON_FIREVERTICES( rmesa );    /* don't pipeline cliprect changes */
-      radeonUpdateScissor( ctx );
-   }
-
-}
-
-
 /* =============================================================
  * Culling
  */
@@ -545,7 +529,8 @@ static void radeonPolygonOffset( GLcontext *ctx,
                                 GLfloat factor, GLfloat units )
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
-   float_ui32_type constant =  { units * rmesa->radeon.state.depth.scale };
+   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+   float_ui32_type constant =  { units * depthScale };
    float_ui32_type factoru = { factor };
 
    RADEON_STATECHANGE( rmesa, zbs );
@@ -567,7 +552,7 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 
    /* TODO: push this into cmd mechanism
     */
-   RADEON_FIREVERTICES( rmesa );
+   radeon_firevertices(&rmesa->radeon);
    LOCK_HARDWARE( &rmesa->radeon );
 
    /* FIXME: Use window x,y offsets into stipple RAM.
@@ -1407,15 +1392,25 @@ void radeonUpdateWindow( GLcontext *ctx )
    GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
    GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
    const GLfloat *v = ctx->Viewport._WindowMap.m;
+   const GLboolean render_to_fbo = (ctx->DrawBuffer ? (ctx->DrawBuffer->Name != 0) : 0);
+   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+   GLfloat y_scale, y_bias;
+
+   if (render_to_fbo) {
+      y_scale = 1.0;
+      y_bias = 0;
+   } else {
+      y_scale = -1.0;
+      y_bias = yoffset;
+   }
 
    float_ui32_type sx = { v[MAT_SX] };
    float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
-   float_ui32_type sy = { - v[MAT_SY] };
-   float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
-   float_ui32_type sz = { v[MAT_SZ] * rmesa->radeon.state.depth.scale };
-   float_ui32_type tz = { v[MAT_TZ] * rmesa->radeon.state.depth.scale };
+   float_ui32_type sy = { v[MAT_SY] * y_scale };
+   float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y };
+   float_ui32_type sz = { v[MAT_SZ] * depthScale };
+   float_ui32_type tz = { v[MAT_TZ] * depthScale };
 
-   RADEON_FIREVERTICES( rmesa );
    RADEON_STATECHANGE( rmesa, vpt );
 
    rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
@@ -1435,6 +1430,8 @@ static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
     * values, or keep the originals hanging around.
     */
    radeonUpdateWindow( ctx );
+
+   radeon_viewport(ctx, x, y, width, height);
 }
 
 static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
@@ -1549,49 +1546,6 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
    rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
 }
 
-
-/**
- * Called via glDrawBuffer.
- */
-static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
-{
-   r100ContextPtr rmesa = R100_CONTEXT(ctx);
-
-   if (RADEON_DEBUG & DEBUG_DRI)
-      fprintf(stderr, "%s %s\n", __FUNCTION__,
-             _mesa_lookup_enum_by_nr( mode ));
-
-   RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
-
-   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
-      /* 0 (GL_NONE) buffers or multiple color drawing buffers */
-      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
-      return;
-   }
-
-   switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
-   case BUFFER_FRONT_LEFT:
-   case BUFFER_BACK_LEFT:
-      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      break;
-   default:
-      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
-      return;
-   }
-
-   radeonSetCliprects( &rmesa->radeon );
-
-   /* We'll set the drawing engine's offset/pitch parameters later
-    * when we update other state.
-    */
-}
-
-static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
-{
-   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
-}
-
-
 /* =============================================================
  * State enable/disable
  */
@@ -1843,21 +1797,30 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
    }
 
    case GL_SCISSOR_TEST:
-      RADEON_FIREVERTICES( rmesa );
+      radeon_firevertices(&rmesa->radeon);
       rmesa->radeon.state.scissor.enabled = state;
       radeonUpdateScissor( ctx );
       break;
 
    case GL_STENCIL_TEST:
-      if ( rmesa->radeon.state.stencil.hwBuffer ) {
-        RADEON_STATECHANGE( rmesa, ctx );
-        if ( state ) {
-           rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_STENCIL_ENABLE;
+      {
+        GLboolean hw_stencil = GL_FALSE;
+        if (ctx->DrawBuffer) {
+           struct radeon_renderbuffer *rrbStencil
+              = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+           hw_stencil = (rrbStencil && rrbStencil->bo);
+        }
+
+        if (hw_stencil) {
+           RADEON_STATECHANGE( rmesa, ctx );
+           if ( state ) {
+              rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_STENCIL_ENABLE;
+           } else {
+              rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+           }
         } else {
-           rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+           FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
         }
-      } else {
-        FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
       }
       break;
 
@@ -2081,43 +2044,61 @@ static void update_texturematrix( GLcontext *ctx )
    }
 }
 
-
-/**
- * Tell the card where to render (offset, pitch).
- * Effected by glDrawBuffer, etc
- */
-void
-radeonUpdateDrawBuffer(GLcontext *ctx)
+static GLboolean r100ValidateBuffers(GLcontext *ctx)
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
-   struct gl_framebuffer *fb = ctx->DrawBuffer;
    struct radeon_renderbuffer *rrb;
+   int i;
 
-   if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
-     /* draw to front */
-     rrb = (void *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
-   } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
-     /* draw to back */
-     rrb = (void *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
-   } else {
-     /* drawing to multiple buffers, or none */
-     return;
+   radeon_validate_reset_bos(&rmesa->radeon);
+   
+   rrb = radeon_get_colorbuffer(&rmesa->radeon);
+   /* color buffer */
+   if (rrb && rrb->bo) {
+     radeon_validate_bo(&rmesa->radeon, rrb->bo,
+                       0, RADEON_GEM_DOMAIN_VRAM);
    }
 
-   assert(rrb);
-   assert(rrb->pitch);
+   /* depth buffer */
+   rrb = radeon_get_depthbuffer(&rmesa->radeon);
+   /* color buffer */
+   if (rrb && rrb->bo) {
+     radeon_validate_bo(&rmesa->radeon, rrb->bo,
+                       0, RADEON_GEM_DOMAIN_VRAM);
+   }
 
-   RADEON_STATECHANGE( rmesa, ctx );
-}
+   for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+      radeonTexObj *t;
+      
+      if (!ctx->Texture.Unit[i]._ReallyEnabled)
+        continue;
+
+      t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+      if (t->image_override && t->bo)
+       radeon_validate_bo(&rmesa->radeon, t->bo,
+                          RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+      else if (t->mt->bo)
+       radeon_validate_bo(&rmesa->radeon, t->mt->bo,
+                          RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+   }
 
+   if (rmesa->radeon.dma.current)
+       radeon_validate_bo(&rmesa->radeon, rmesa->radeon.dma.current,
+                         RADEON_GEM_DOMAIN_GTT, 0);
 
-void radeonValidateState( GLcontext *ctx )
+   return radeon_revalidate_bos(ctx);
+}
+
+GLboolean radeonValidateState( GLcontext *ctx )
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint new_state = rmesa->radeon.NewGLState;
 
    if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
-     radeonUpdateDrawBuffer(ctx);
+     _mesa_update_framebuffer(ctx);
+     /* this updates the DrawBuffer's Width/Height if it's a FBO */
+     _mesa_update_draw_buffer_bounds(ctx);
+     RADEON_STATECHANGE(rmesa, ctx);
    }
 
    if (new_state & _NEW_TEXTURE) {
@@ -2125,6 +2106,10 @@ void radeonValidateState( GLcontext *ctx )
       new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
    }
 
+   /* we need to do a space check here */
+   if (!r100ValidateBuffers(ctx))
+     return GL_FALSE;
+
    /* Need an event driven matrix update?
     */
    if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 
@@ -2200,7 +2185,8 @@ static void radeonWrapRunPipeline( GLcontext *ctx )
    /* Validate state:
     */
    if (rmesa->radeon.NewGLState)
-      radeonValidateState( ctx );
+      if (!radeonValidateState( ctx ))
+        FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
 
    has_material = (ctx->Light.Enabled && check_material( ctx ));