OSDN Git Service

Implement GLX_SGI_make_current_read
authorIan Romanick <idr@us.ibm.com>
Fri, 10 Nov 2006 00:14:30 +0000 (00:14 +0000)
committerIan Romanick <idr@us.ibm.com>
Fri, 10 Nov 2006 00:14:30 +0000 (00:14 +0000)
Discontinue use of the old GetBuffeSize interface.  Track both the
current read-drawable and the current draw-drawable.  After moving
some context state to via_rednerbuffer, GLX_SGI_make_current_read can
be enabled.

The extension works, but the wincopy test prodcues a black window for
the destination window.  After messing around with the window and
looking at the code, I believe the problem is in the handling of
buffer swap requests on a drawable that isn't the current draw-drawable.

src/mesa/drivers/dri/unichrome/via_context.c
src/mesa/drivers/dri/unichrome/via_context.h
src/mesa/drivers/dri/unichrome/via_ioctl.c
src/mesa/drivers/dri/unichrome/via_screen.c
src/mesa/drivers/dri/unichrome/via_span.c
src/mesa/drivers/dri/unichrome/via_state.c

index fa14318..49c2465 100644 (file)
@@ -147,10 +147,13 @@ viaRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb,
 
 
 static void
-viaInitRenderbuffer(struct gl_renderbuffer *rb, GLenum format)
+viaInitRenderbuffer(struct via_renderbuffer *vrb, GLenum format,
+                   __DRIdrawablePrivate *dPriv)
 {
    const GLuint name = 0;
+   struct gl_renderbuffer *rb = & vrb->Base;
 
+   vrb->dPriv = dPriv;
    _mesa_init_renderbuffer(rb, name);
 
    /* Make sure we're using a null-valued GetPointer routine */
@@ -198,8 +201,9 @@ viaInitRenderbuffer(struct gl_renderbuffer *rb, GLenum format)
  * \sa AllocateBuffer
  */
 static GLboolean
-calculate_buffer_parameters( struct via_context *vmesa,
-                             struct gl_framebuffer *fb )
+calculate_buffer_parameters(struct via_context *vmesa,
+                           struct gl_framebuffer *fb,
+                           __DRIdrawablePrivate *dPriv)
 {
    const unsigned shift = vmesa->viaScreen->bitsPerPixel / 16;
    const unsigned extra = 32;
@@ -215,26 +219,28 @@ calculate_buffer_parameters( struct via_context *vmesa,
 
    if (!vmesa->front.Base.InternalFormat) {
       /* do one-time init for the renderbuffers */
-      viaInitRenderbuffer(&vmesa->front.Base, GL_RGBA);
+      viaInitRenderbuffer(&vmesa->front, GL_RGBA, dPriv);
       viaSetSpanFunctions(&vmesa->front, &fb->Visual);
       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &vmesa->front.Base);
 
       if (fb->Visual.doubleBufferMode) {
-         viaInitRenderbuffer(&vmesa->back.Base, GL_RGBA);
+         viaInitRenderbuffer(&vmesa->back, GL_RGBA, dPriv);
          viaSetSpanFunctions(&vmesa->back, &fb->Visual);
          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &vmesa->back.Base);
       }
 
       if (vmesa->glCtx->Visual.depthBits > 0) {
-         viaInitRenderbuffer(&vmesa->depth.Base, 
+         viaInitRenderbuffer(&vmesa->depth,
                              (vmesa->glCtx->Visual.depthBits == 16
-                              ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24));
+                              ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24),
+                            dPriv);
          viaSetSpanFunctions(&vmesa->depth, &fb->Visual);
          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &vmesa->depth.Base);
       }
 
       if (vmesa->glCtx->Visual.stencilBits > 0) {
-         viaInitRenderbuffer(&vmesa->stencil.Base, GL_STENCIL_INDEX8_EXT);
+         viaInitRenderbuffer(&vmesa->stencil, GL_STENCIL_INDEX8_EXT,
+                            dPriv);
          viaSetSpanFunctions(&vmesa->stencil, &fb->Visual);
          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &vmesa->stencil.Base);
       }
@@ -243,11 +249,9 @@ calculate_buffer_parameters( struct via_context *vmesa,
    assert(vmesa->front.Base.InternalFormat);
    assert(vmesa->front.Base.AllocStorage);
    if (fb->Visual.doubleBufferMode) {
-      assert(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
-      assert(vmesa->front.Base.AllocStorage);
+      assert(vmesa->back.Base.AllocStorage);
    }
    if (fb->Visual.depthBits) {
-      assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
       assert(vmesa->depth.Base.AllocStorage);
    }
 
@@ -352,19 +356,11 @@ void viaReAllocateBuffers(GLcontext *ctx, GLframebuffer *drawbuffer,
 {
     struct via_context *vmesa = VIA_CONTEXT(ctx);
 
-    calculate_buffer_parameters( vmesa, drawbuffer );
+    calculate_buffer_parameters(vmesa, drawbuffer, vmesa->driDrawable);
 
     _mesa_resize_framebuffer(ctx, drawbuffer, width, height);
 }
 
-static void viaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
-{
-    GET_CURRENT_CONTEXT(ctx);
-    struct via_context *vmesa = VIA_CONTEXT(ctx);       
-    *width = vmesa->driDrawable->w;
-    *height = vmesa->driDrawable->h;
-}
-
 /* Extension strings exported by the Unichrome driver.
  */
 const struct dri_extension card_extensions[] =
@@ -579,7 +575,6 @@ viaCreateContext(const __GLcontextModes *visual,
     ctx->Const.MaxPointSizeAA = 1.0;
     ctx->Const.PointSizeGranularity = 1.0;
 
-    ctx->Driver.GetBufferSize = viaBufferSize;
     ctx->Driver.GetString = viaGetString;
 
     ctx->DriverCtx = (void *)vmesa;
@@ -734,50 +729,72 @@ viaDestroyContext(__DRIcontextPrivate *driContextPriv)
 
 void viaXMesaWindowMoved(struct via_context *vmesa)
 {
-   __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+   __DRIdrawablePrivate *const drawable = vmesa->driDrawable;
+   __DRIdrawablePrivate *const readable = vmesa->driReadable;
+   struct via_renderbuffer *const draw_buffer = 
+     (struct via_renderbuffer *) drawable->driverPrivate;
+   struct via_renderbuffer *const read_buffer =
+     (struct via_renderbuffer *) readable->driverPrivate;
    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
 
-   if (!dPriv)
+   if (!drawable)
       return;
    
    switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
    case BUFFER_BIT_BACK_LEFT: 
-      if (dPriv->numBackClipRects == 0) {
-        vmesa->numClipRects = dPriv->numClipRects;
-        vmesa->pClipRects = dPriv->pClipRects;
+      if (drawable->numBackClipRects == 0) {
+        vmesa->numClipRects = drawable->numClipRects;
+        vmesa->pClipRects = drawable->pClipRects;
       } 
       else {
-        vmesa->numClipRects = dPriv->numBackClipRects;
-        vmesa->pClipRects = dPriv->pBackClipRects;
+        vmesa->numClipRects = drawable->numBackClipRects;
+        vmesa->pClipRects = drawable->pBackClipRects;
       }
       break;
    case BUFFER_BIT_FRONT_LEFT:
-      vmesa->numClipRects = dPriv->numClipRects;
-      vmesa->pClipRects = dPriv->pClipRects;
+      vmesa->numClipRects = drawable->numClipRects;
+      vmesa->pClipRects = drawable->pClipRects;
       break;
    default:
       vmesa->numClipRects = 0;
       break;
    }
 
-   if (vmesa->drawW != dPriv->w ||
-       vmesa->drawH != dPriv->h) 
-      calculate_buffer_parameters( vmesa, vmesa->glCtx->DrawBuffer );
+   if ((draw_buffer->drawW != drawable->w) 
+       || (draw_buffer->drawH != drawable->h)) {
+      calculate_buffer_parameters(vmesa, vmesa->glCtx->DrawBuffer,
+                                 drawable);
+   }
 
-   vmesa->drawXoff = (GLuint)(((dPriv->x * bytePerPixel) & 0x1f) / 
+   draw_buffer->drawXoff = (GLuint)(((drawable->x * bytePerPixel) & 0x1f) / 
                              bytePerPixel);  
-   vmesa->drawX = dPriv->x - vmesa->drawXoff;
-   vmesa->drawY = dPriv->y;
-   vmesa->drawW = dPriv->w;
-   vmesa->drawH = dPriv->h;
+   draw_buffer->drawX = drawable->x - draw_buffer->drawXoff;
+   draw_buffer->drawY = drawable->y;
+   draw_buffer->drawW = drawable->w;
+   draw_buffer->drawH = drawable->h;
+
+   if (drawable != readable) {
+      if ((read_buffer->drawW != readable->w) 
+         || (read_buffer->drawH != readable->h)) {
+        calculate_buffer_parameters(vmesa, vmesa->glCtx->ReadBuffer,
+                                    readable);
+      }
+
+      read_buffer->drawXoff = (GLuint)(((readable->x * bytePerPixel) & 0x1f) / 
+                                      bytePerPixel);  
+      read_buffer->drawX = readable->x - read_buffer->drawXoff;
+      read_buffer->drawY = readable->y;
+      read_buffer->drawW = readable->w;
+      read_buffer->drawH = readable->h;
+   }
 
    vmesa->front.orig = (vmesa->front.offset + 
-                       vmesa->drawY * vmesa->front.pitch + 
-                       vmesa->drawX * bytePerPixel);
+                       draw_buffer->drawY * vmesa->front.pitch + 
+                       draw_buffer->drawX * bytePerPixel);
 
    vmesa->front.origMap = (vmesa->front.map + 
-                          vmesa->drawY * vmesa->front.pitch + 
-                          vmesa->drawX * bytePerPixel);
+                          draw_buffer->drawY * vmesa->front.pitch + 
+                          draw_buffer->drawX * bytePerPixel);
 
    vmesa->back.orig = vmesa->back.offset;
    vmesa->depth.orig = vmesa->depth.offset;   
@@ -813,15 +830,41 @@ viaMakeCurrent(__DRIcontextPrivate *driContextPriv,
         drawBuffer = (GLframebuffer *)driDrawPriv->driverPrivate;
         readBuffer = (GLframebuffer *)driReadPriv->driverPrivate;
 
-       if ( vmesa->driDrawable != driDrawPriv ) {
-          driDrawableInitVBlank( driDrawPriv, vmesa->vblank_flags,
-                                 &vmesa->vbl_seq );
-          vmesa->driDrawable = driDrawPriv;
-          if ( ! calculate_buffer_parameters( vmesa, drawBuffer ) ) {
-             return GL_FALSE;
-          }
+       if (vmesa->driDrawable != driDrawPriv) {
+          driDrawableInitVBlank(driDrawPriv, vmesa->vblank_flags,
+                                &vmesa->vbl_seq);
        }
 
+       if ((vmesa->driDrawable != driDrawPriv)
+          || (vmesa->driReadable != driReadPriv)) {
+         vmesa->driDrawable = driDrawPriv;
+         vmesa->driReadable = driReadPriv;
+
+         if ((drawBuffer->Width != driDrawPriv->w) 
+             || (drawBuffer->Height != driDrawPriv->h)) {
+            _mesa_resize_framebuffer(ctx, drawBuffer,
+                                     driDrawPriv->w, driDrawPriv->h);
+            drawBuffer->Initialized = GL_TRUE;
+         }
+
+         if (!calculate_buffer_parameters(vmesa, drawBuffer, driDrawPriv)) {
+            return GL_FALSE;
+         }
+
+         if (driDrawPriv != driReadPriv) {
+            if ((readBuffer->Width != driReadPriv->w)
+                || (readBuffer->Height != driReadPriv->h)) {
+               _mesa_resize_framebuffer(ctx, readBuffer,
+                                        driReadPriv->w, driReadPriv->h);
+               readBuffer->Initialized = GL_TRUE;
+            }
+
+            if (!calculate_buffer_parameters(vmesa, readBuffer, driReadPriv)) {
+               return GL_FALSE;
+            }
+         }
+       }
+
         _mesa_make_current(vmesa->glCtx, drawBuffer, readBuffer);
 
        ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
@@ -847,7 +890,10 @@ void viaGetLock(struct via_context *vmesa, GLuint flags)
 
     drmGetLock(vmesa->driFd, vmesa->hHWContext, flags);
 
-    DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+    DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+    if (dPriv != vmesa->driReadable) {
+       DRI_VALIDATE_DRAWABLE_INFO(sPriv, vmesa->driReadable);
+    }
 
     if (vmesa->sarea->ctxOwner != vmesa->hHWContext) {
        vmesa->sarea->ctxOwner = vmesa->hHWContext;
index 9d7a0e6..77161a8 100644 (file)
@@ -98,6 +98,18 @@ struct via_renderbuffer {
                         * at (drawX,drawY) in screen space.
                         */
    char *origMap;
+
+   int drawX;                   /* origin of drawable in draw buffer */
+   int drawY;    
+   int drawW;                  
+   int drawH;    
+
+   int drawXoff;               /* drawX is 32byte aligned - this is
+                                * the delta to the real origin, in
+                                * pixel units.
+                                */
+
+   __DRIdrawablePrivate *dPriv;
 };
 
 
@@ -272,16 +284,6 @@ struct via_context {
 
    struct via_renderbuffer *drawBuffer;
 
-   int drawX;                   /* origin of drawable in draw buffer */
-   int drawY;    
-   int drawW;                  
-   int drawH;    
-
-   int drawXoff;               /* drawX is 32byte aligned - this is
-                                * the delta to the real origin, in
-                                * pixel units.
-                                */
-
    GLuint numClipRects;         /* cliprects for that buffer */
    drm_clip_rect_t *pClipRects;
 
@@ -294,7 +296,16 @@ struct via_context {
    int driFd;
    __DRInativeDisplay *display;
 
-   __DRIdrawablePrivate *driDrawable;
+   /**
+    * DRI drawable bound to this context for drawing.
+    */
+   __DRIdrawablePrivate        *driDrawable;
+
+   /**
+    * DRI drawable bound to this context for reading.
+    */
+   __DRIdrawablePrivate        *driReadable;
+
    __DRIscreenPrivate *driScreen;
    viaScreenPrivate *viaScreen;
    drm_via_sarea_t *sarea;
index dd2e93b..5d102de 100644 (file)
@@ -182,8 +182,8 @@ static void viaFillBuffer(struct via_context *vmesa,
    GLuint i;
 
    for (i = 0; i < nboxes ; i++) {        
-      int x = pbox[i].x1 - vmesa->drawX;
-      int y = pbox[i].y1 - vmesa->drawY;
+      int x = pbox[i].x1 - buffer->drawX;
+      int y = pbox[i].y1 - buffer->drawY;
       int w = pbox[i].x2 - pbox[i].x1;
       int h = pbox[i].y2 - pbox[i].y1;
 
@@ -206,6 +206,8 @@ static void viaClear(GLcontext *ctx, GLbitfield mask)
 {
    struct via_context *vmesa = VIA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+   struct via_renderbuffer *const vrb = 
+     (struct via_renderbuffer *) dPriv->driverPrivate;
    int flag = 0;
    GLuint i = 0;
    GLuint clear_depth_mask = 0xf << 28;
@@ -274,8 +276,8 @@ static void viaClear(GLcontext *ctx, GLbitfield mask)
 
       /* flip top to bottom */
       cy = dPriv->h - cy - ch;
-      cx += vmesa->drawX + vmesa->drawXoff;
-      cy += vmesa->drawY;
+      cx += vrb->drawX + vrb->drawXoff;
+      cy += vrb->drawY;
         
       if (!all) {
         drm_clip_rect_t *b = vmesa->pClipRects;         
@@ -352,8 +354,8 @@ static void viaDoSwapBuffers(struct via_context *vmesa,
    GLuint i;
         
    for (i = 0; i < nbox; i++, b++) {        
-      GLint x = b->x1 - vmesa->drawX;
-      GLint y = b->y1 - vmesa->drawY;
+      GLint x = b->x1 - back->drawX;
+      GLint y = b->y1 - back->drawY;
       GLint w = b->x2 - b->x1;
       GLint h = b->y2 - b->y1;
        
@@ -766,7 +768,7 @@ static void via_emit_cliprect(struct via_context *vmesa,
    vb[4] = (HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF);
    vb[5] = (HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000) >> 24); 
 
-   vb[6] = (HC_SubA_HSPXYOS << 24) | ((31-vmesa->drawXoff) << HC_HSPXOS_SHIFT);
+   vb[6] = (HC_SubA_HSPXYOS << 24) | ((31 - buffer->drawXoff) << HC_HSPXOS_SHIFT);
    vb[7] = (HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch;
 }
 
@@ -881,21 +883,25 @@ void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags)
    }
    else if (vmesa->numClipRects) {
       drm_clip_rect_t *pbox = vmesa->pClipRects;
-      
+      __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+      struct via_renderbuffer *const vrb = 
+       (struct via_renderbuffer *) dPriv->driverPrivate;
+
+
       for (i = 0; i < vmesa->numClipRects; i++) {
         drm_clip_rect_t b;
 
-        b.x1 = pbox[i].x1 - (vmesa->drawX + vmesa->drawXoff);
-        b.x2 = pbox[i].x2 - (vmesa->drawX + vmesa->drawXoff);
-        b.y1 = pbox[i].y1 - vmesa->drawY;
-        b.y2 = pbox[i].y2 - vmesa->drawY;
+        b.x1 = pbox[i].x1 - (vrb->drawX + vrb->drawXoff);
+        b.x2 = pbox[i].x2 - (vrb->drawX + vrb->drawXoff);
+        b.y1 = pbox[i].y1 - vrb->drawY;
+        b.y2 = pbox[i].y2 - vrb->drawY;
 
         if (vmesa->scissor &&
             !intersect_rect(&b, &b, &vmesa->scissorRect)) 
            continue;
 
-        b.x1 += vmesa->drawXoff;
-        b.x2 += vmesa->drawXoff;
+        b.x1 += vrb->drawXoff;
+        b.x2 += vrb->drawXoff;
 
         via_emit_cliprect(vmesa, &b);
 
index 98a742c..28e1f94 100644 (file)
@@ -182,6 +182,7 @@ viaInitDriver(__DRIscreenPrivate *sPriv)
          (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
        }
 
+       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
        (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
     }
 
index 6ff95cc..f1ed980 100644 (file)
 
 #undef LOCAL_VARS
 #define LOCAL_VARS                                                     \
-    struct via_context *vmesa = VIA_CONTEXT(ctx);                      \
-    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;                  \
     struct via_renderbuffer *vrb = (struct via_renderbuffer *) rb;     \
+    __DRIdrawablePrivate *dPriv = vrb->dPriv;                           \
     GLuint pitch = vrb->pitch;                                          \
     GLuint height = dPriv->h;                                          \
     GLint p = 0;                                                       \
-    char *buf = (char *)(vrb->origMap + vmesa->drawXoff * vrb->bpp);    \
+    char *buf = (char *)(vrb->origMap + vrb->drawXoff * vrb->bpp);      \
     (void) p;
 
 /* ================================================================
 /* 16 bit depthbuffer functions.
  */
 #define LOCAL_DEPTH_VARS                                            \
-    struct via_context *vmesa = VIA_CONTEXT(ctx);                   \
-    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;               \
     struct via_renderbuffer *vrb = (struct via_renderbuffer *) rb;  \
+    __DRIdrawablePrivate *dPriv = vrb->dPriv;                       \
     GLuint depth_pitch = vrb->pitch;                                \
     GLuint height = dPriv->h;                                       \
-    char *buf = (char *)(vrb->map + (vmesa->drawXoff * vrb->bpp/8))
+    char *buf = (char *)(vrb->map + (vrb->drawXoff * vrb->bpp/8))
 
 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS 
 
index c001661..2c9cfca 100644 (file)
@@ -476,6 +476,9 @@ void viaEmitState(struct via_context *vmesa)
     */
    if (ctx->Polygon.StippleFlag) {
       GLuint *stipple = &ctx->PolygonStipple[0];
+      __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+      struct via_renderbuffer *const vrb = 
+       (struct via_renderbuffer *) dPriv->driverPrivate;
       GLint i;
         
       BEGIN_RING(38);
@@ -498,9 +501,9 @@ void viaEmitState(struct via_context *vmesa)
       OUT_RING( HC_HEADER2 );                     
       OUT_RING( (HC_ParaType_NotTex << 16) );
       OUT_RING( (HC_SubA_HSPXYOS << 24) | 
-               (((32- vmesa->drawXoff) & 0x1f) << HC_HSPXOS_SHIFT));
+               (((32- vrb->drawXoff) & 0x1f) << HC_HSPXOS_SHIFT));
       OUT_RING( (HC_SubA_HSPXYOS << 24) | 
-               (((32 - vmesa->drawXoff) & 0x1f) << HC_HSPXOS_SHIFT));
+               (((32 - vrb->drawXoff) & 0x1f) << HC_HSPXOS_SHIFT));
 
       ADVANCE_RING();
    }
@@ -720,15 +723,18 @@ static void viaColorMask(GLcontext *ctx,
 void viaCalcViewport(GLcontext *ctx)
 {
     struct via_context *vmesa = VIA_CONTEXT(ctx);
+    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+    struct via_renderbuffer *const vrb = 
+      (struct via_renderbuffer *) dPriv->driverPrivate;
     const GLfloat *v = ctx->Viewport._WindowMap.m;
     GLfloat *m = vmesa->ViewportMatrix.m;
     
     /* See also via_translate_vertex.
      */
     m[MAT_SX] =   v[MAT_SX];
-    m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X + vmesa->drawXoff;
+    m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X + vrb->drawXoff;
     m[MAT_SY] = - v[MAT_SY];
-    m[MAT_TY] = - v[MAT_TY] + vmesa->driDrawable->h + SUBPIXEL_Y;
+    m[MAT_TY] = - v[MAT_TY] + dPriv->h + SUBPIXEL_Y;
     m[MAT_SZ] =   v[MAT_SZ] * (1.0 / vmesa->depth_max);
     m[MAT_TZ] =   v[MAT_TZ] * (1.0 / vmesa->depth_max);
 }