static void do_draw_pix( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLint pitch, const void *pixels, GLuint dest ) { intelContextPtr intel = INTEL_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = intel->driDrawable; drm_clip_rect_t *box = dPriv->pClipRects; int nbox = dPriv->numClipRects; int i; int src_offset = intelAgpOffsetFromVirtual( intel, pixels); int src_pitch = pitch; assert(src_offset != ~0); /* should be caught earlier */ if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); if (ctx->DrawBuffer) { y -= height; /* cope with pixel zoom */ if (!clip_pixelrect(ctx, ctx->DrawBuffer, &x, &y, &width, &height)) { UNLOCK_HARDWARE( intel ); return; } y = dPriv->h - y - height; /* convert from gl to hardware coords */ x += dPriv->x; y += dPriv->y; for (i = 0 ; i < nbox ; i++ ) { GLint bx, by, bw, bh; if (intersect_region(box + i, x, y, width, height, &bx, &by, &bw, &bh)) { intelEmitCopyBlitLocked( intel, intel->intelScreen->cpp, src_pitch, src_offset, intel->intelScreen->front.pitch, intel->drawRegion->offset, bx - x, by - y, bx, by, bw, bh ); } } } UNLOCK_HARDWARE( intel ); intelFinish( &intel->ctx ); }
static void do_draw_pix( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLint pitch, const void *pixels, GLuint planemask) { r200ContextPtr rmesa = R200_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; drm_clip_rect_t *box = dPriv->pClipRects; struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorDrawBuffers[0][0]; driRenderbuffer *drb = (driRenderbuffer *) rb; int nbox = dPriv->numClipRects; int i; int blit_format; int size; int src_offset = r200GartOffsetFromVirtual( rmesa, pixels ); int src_pitch = pitch * rmesa->r200Screen->cpp; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); switch ( rmesa->r200Screen->cpp ) { case 2: blit_format = R200_CP_COLOR_FORMAT_RGB565; break; case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; default: return; } LOCK_HARDWARE( rmesa ); if (rmesa->store.cmd_used) r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); y -= height; /* cope with pixel zoom */ if (!clip_pixelrect(ctx, ctx->DrawBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( rmesa ); return; } y = dPriv->h - y - height; /* convert from gl to hardware coords */ x += dPriv->x; y += dPriv->y; r200EmitWait( rmesa, RADEON_WAIT_3D ); for (i = 0 ; i < nbox ; i++ ) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; r200EmitBlit( rmesa, blit_format, src_pitch, src_offset, drb->pitch * drb->cpp, drb->offset + rmesa->r200Screen->fbLocation, bx - x, by - y, bx, by, bw, bh ); } r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); r200WaitForIdleLocked( rmesa ); /* required by GL */ UNLOCK_HARDWARE( rmesa ); }
static GLboolean r200TryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *pixels ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); GLint pitch = pack->RowLength ? pack->RowLength : width; GLint blit_format; GLuint cpp = rmesa->r200Screen->cpp; GLint size = width * height * cpp; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); /* Only accelerate reading to GART buffers. */ if ( !r200IsGartMemory(rmesa, pixels, pitch * height * rmesa->r200Screen->cpp ) ) { if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: dest not GART\n", __FUNCTION__); return GL_FALSE; } /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from * blitter: */ if (!pack->Invert) { if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); return GL_FALSE; } if (!check_color(ctx, type, format, pack, pixels, size, pitch)) return GL_FALSE; switch ( rmesa->r200Screen->cpp ) { case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; default: return GL_FALSE; } /* Although the blits go on the command buffer, need to do this and * fire with lock held to guarentee cliprects and drawOffset are * correct. * * This is an unusual situation however, as the code which flushes * a full command buffer expects to be called unlocked. As a * workaround, immediately flush the buffer on aquiring the lock. */ LOCK_HARDWARE( rmesa ); if (rmesa->store.cmd_used) r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( rmesa ); if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s totally clipped -- nothing to do\n", __FUNCTION__); return GL_TRUE; } { __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; driRenderbuffer *drb = (driRenderbuffer *) ctx->ReadBuffer->_ColorReadBuffer; int nbox = dPriv->numClipRects; int src_offset = drb->offset + rmesa->r200Screen->fbLocation; int src_pitch = drb->pitch * drb->cpp; int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels ); int dst_pitch = pitch * rmesa->r200Screen->cpp; drm_clip_rect_t *box = dPriv->pClipRects; int i; r200EmitWait( rmesa, RADEON_WAIT_3D ); y = dPriv->h - y - height; x += dPriv->x; y += dPriv->y; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", src_pitch, dst_pitch); for (i = 0 ; i < nbox ; i++) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; r200EmitBlit( rmesa, blit_format, src_pitch, src_offset, dst_pitch, dst_offset, bx, by, bx - x, by - y, bw, bh ); } r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); } UNLOCK_HARDWARE( rmesa ); r200Finish( ctx ); /* required by GL */ return GL_TRUE; }
static GLboolean intelTryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *pixels ) { intelContextPtr intel = INTEL_CONTEXT(ctx); GLint size = 0; /* not really used */ GLint pitch = pack->RowLength ? pack->RowLength : width; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); /* Only accelerate reading to agp buffers. */ if ( !intelIsAgpMemory(intel, pixels, pitch * height * intel->intelScreen->cpp ) ) { if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); return GL_FALSE; } /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from * blitter: */ if (!pack->Invert) { if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); return GL_FALSE; } if (!check_color(ctx, type, format, pack, pixels, size, pitch)) return GL_FALSE; switch ( intel->intelScreen->cpp ) { case 4: break; default: return GL_FALSE; } /* Although the blits go on the command buffer, need to do this and * fire with lock held to guarentee cliprects and drawing offset are * correct. * * This is an unusual situation however, as the code which flushes * a full command buffer expects to be called unlocked. As a * workaround, immediately flush the buffer on aquiring the lock. */ intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); { __DRIdrawablePrivate *dPriv = intel->driDrawable; int nbox = dPriv->numClipRects; int src_offset = intel->readRegion->offset; int src_pitch = intel->intelScreen->front.pitch; int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); drm_clip_rect_t *box = dPriv->pClipRects; int i; assert(dst_offset != ~0); /* should have been caught above */ if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) { UNLOCK_HARDWARE( intel ); if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s totally clipped -- nothing to do\n", __FUNCTION__); return GL_TRUE; } /* convert to screen coords (y=0=top) */ y = dPriv->h - y - height; x += dPriv->x; y += dPriv->y; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", src_pitch, pitch); /* We don't really have to do window clipping for readpixels. * The OpenGL spec says that pixels read from outside the * visible window region (pixel ownership) have undefined value. */ for (i = 0 ; i < nbox ; i++) { GLint bx, by, bw, bh; if (intersect_region(box+i, x, y, width, height, &bx, &by, &bw, &bh)) { intelEmitCopyBlitLocked( intel, intel->intelScreen->cpp, src_pitch, src_offset, pitch, dst_offset, bx, by, bx - x, by - y, bw, bh ); } } } UNLOCK_HARDWARE( intel ); intelFinish( &intel->ctx ); return GL_TRUE; }
static void do_draw_pix( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLint pitch, const void *pixels, GLuint dest ) { intelContextPtr intel = INTEL_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = intel->driDrawable; drm_clip_rect_t *box = dPriv->pClipRects; int nbox = dPriv->numClipRects; int i; int size; int src_offset = intelAgpOffsetFromVirtual( intel, pixels); int src_pitch = pitch; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); if (ctx->DrawBuffer) { y -= height; /* cope with pixel zoom */ if (!clip_pixelrect(ctx, ctx->DrawBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( intel ); return; } y = dPriv->h - y - height; /* convert from gl to hardware coords */ x += dPriv->x; y += dPriv->y; for (i = 0 ; i < nbox ; i++ ) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; intelEmitCopyBlitLocked( intel, intel->intelScreen->cpp, src_pitch, src_offset, intel->intelScreen->frontPitch, intel->drawOffset, bx - x, by - y, bx, by, bw, bh ); } } UNLOCK_HARDWARE( intel ); intelFinish( &intel->ctx ); }
static GLboolean intelTryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *pixels ) { intelContextPtr intel = INTEL_CONTEXT(ctx); GLint size = 0; GLint pitch = pack->RowLength ? pack->RowLength : width; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); /* Only accelerate reading to agp buffers. */ if ( !intelIsAgpMemory(intel, pixels, pitch * height * intel->intelScreen->cpp ) ) { if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); return GL_FALSE; } /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from * blitter: */ if (!pack->Invert) { if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); return GL_FALSE; } if (!check_color(ctx, type, format, pack, pixels, size, pitch)) return GL_FALSE; switch ( intel->intelScreen->cpp ) { case 4: break; default: return GL_FALSE; } /* Although the blits go on the command buffer, need to do this and * fire with lock held to guarentee cliprects and drawOffset are * correct. * * This is an unusual situation however, as the code which flushes * a full command buffer expects to be called unlocked. As a * workaround, immediately flush the buffer on aquiring the lock. */ intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); { __DRIdrawablePrivate *dPriv = intel->driDrawable; int nbox = dPriv->numClipRects; int src_offset = intel->drawOffset; int src_pitch = intel->intelScreen->frontPitch; int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); drm_clip_rect_t *box = dPriv->pClipRects; int i; if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, &size)) { UNLOCK_HARDWARE( intel ); if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s totally clipped -- nothing to do\n", __FUNCTION__); return GL_TRUE; } y = dPriv->h - y - height; x += dPriv->x; y += dPriv->y; if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", src_pitch, pitch); for (i = 0 ; i < nbox ; i++) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; intelEmitCopyBlitLocked( intel, intel->intelScreen->cpp, src_pitch, src_offset, pitch, dst_offset, bx, by, bx - x, by - y, bw, bh ); } } UNLOCK_HARDWARE( intel ); intelFinish( &intel->ctx ); return GL_TRUE; }
static GLboolean mgaTryDrawPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); GLint size, skipPixels, skipRows; GLint pitch = unpack->RowLength ? unpack->RowLength : width; GLuint dest, planemask; GLuint cpp = mmesa->mgaScreen->cpp; if (!clip_pixelrect(ctx, ctx->DrawBuffer, &x, &y, &width, &height, &skipPixels, &skipRows, &size)) { return GL_TRUE; } switch (format) { #if defined(MESA_packed_depth_stencil) case GL_DEPTH_STENCIL_MESA: dest = mmesa->mgaScreen->depthOffset; planemask = ~0; if (!check_depth_stencil_24_8(ctx, type, unpack, pixels, size, pitch) || !check_depth_per_fragment_ops(ctx) || !check_stencil_per_fragment_ops(ctx)) return GL_FALSE; break; #endif case GL_DEPTH_COMPONENT: dest = mmesa->mgaScreen->depthOffset; if (ctx->Visual.depthBits == 24) planemask = ~0xff; else planemask = ~0; if (!check_depth(ctx, type, unpack, pixels, size, pitch) || !check_depth_per_fragment_ops(ctx)) return GL_FALSE; break; case GL_RGB: case GL_BGRA: dest = (mmesa->draw_buffer == MGA_FRONT ? mmesa->mgaScreen->frontOffset : mmesa->mgaScreen->backOffset); planemask = mgaPackColor(cpp, ctx->Color.ColorMask[RCOMP], ctx->Color.ColorMask[GCOMP], ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP]); if (cpp == 2) planemask |= planemask << 16; if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { return GL_FALSE; } if (!check_color_per_fragment_ops(ctx)) { return GL_FALSE; } break; default: return GL_FALSE; } LOCK_HARDWARE_QUIESCENT( mmesa ); if (mmesa->dirty_cliprects & MGA_FRONT) mgaUpdateRects( mmesa, MGA_FRONT ); if ( IS_AGP_MEM(mmesa, (char *)pixels) && IS_AGP_MEM(mmesa, (char *)pixels + size) ) { do_draw_pix( ctx, x, y, width, height, pitch, pixels, dest, planemask ); UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); } else { /* Pixels is in regular memory -- get dma buffers and perform * upload through them. */ /* drmBufPtr buf = mgaGetBufferLocked(mmesa); */ GLuint bufferpitch = (width*cpp+31)&~31; char *address = 0; /* mmesa->mgaScreen->agp.map; */ do { /* GLuint rows = MIN2( height, MGA_DMA_BUF_SZ / bufferpitch ); */ GLuint rows = height; if (0) fprintf(stderr, "trying to upload %d rows (pitch %d)\n", rows, bufferpitch); /* The texture conversion code is so slow that there is only * negligble speedup when the buffers/images don't exactly * match: */ #if 0 if (cpp == 2) { if (!_mesa_convert_texsubimage2d( MESA_FORMAT_RGB565, 0, 0, width, rows, bufferpitch, format, type, unpack, pixels, address )) { /* mgaReleaseBufLocked( mmesa, buf ); */ UNLOCK_HARDWARE(mmesa); return GL_FALSE; } } else { if (!_mesa_convert_texsubimage2d( MESA_FORMAT_ARGB8888, 0, 0, width, rows, bufferpitch, format, type, unpack, pixels, address )) { /* mgaReleaseBufLocked( mmesa, buf ); */ UNLOCK_HARDWARE(mmesa); return GL_FALSE; } } #else MEMCPY( address, pixels, rows*bufferpitch ); #endif do_draw_pix( ctx, x, y, width, rows, bufferpitch/cpp, address, dest, planemask ); /* Fix me -- use multiple buffers to avoid flush. */ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); pixels = (void *)((char *) pixels + rows * pitch); height -= rows; y += rows; } while (height); /* mgaReleaseBufLocked( mmesa, buf ); */ } UNLOCK_HARDWARE( mmesa ); mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; return GL_TRUE; }
static GLboolean mgaTryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *pixels ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); GLint size, skipPixels, skipRows; GLint pitch = pack->RowLength ? pack->RowLength : width; GLboolean ok; GLuint planemask; GLuint source; #if 0 drmMGABlit blit; GLuint dest; GLint source_pitch, dest_pitch; GLint delta_sx, delta_sy; GLint delta_dx, delta_dy; GLint blit_height, ydir; #endif if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, &skipPixels, &skipRows, &size)) { return GL_TRUE; } /* Only accelerate reading to agp buffers. */ if ( !IS_AGP_MEM(mmesa, (char *)pixels) || !IS_AGP_MEM(mmesa, (char *)pixels + size) ) return GL_FALSE; switch (format) { #if defined(MESA_packed_depth_stencil) case GL_DEPTH_STENCIL_MESA: ok = check_depth_stencil_24_8(ctx, type, pack, pixels, size, pitch); planemask = ~0; source = mmesa->mgaScreen->depthOffset; break; #endif case GL_DEPTH_COMPONENT: ok = check_depth(ctx, type, pack, pixels, size, pitch); /* Can't accelerate at this depth -- planemask does the wrong * thing; it doesn't clear the low order bits in the * destination, instead it leaves them untouched. * * Could get the acclerator to solid fill the destination with * zeros first... Or get the cpu to do it... */ if (ctx->Visual.depthBits == 24) return GL_FALSE; planemask = ~0; source = mmesa->mgaScreen->depthOffset; break; case GL_RGB: case GL_BGRA: ok = check_color(ctx, type, format, pack, pixels, size, pitch); planemask = ~0; source = (mmesa->draw_buffer == MGA_FRONT ? mmesa->mgaScreen->frontOffset : mmesa->mgaScreen->backOffset); break; default: return GL_FALSE; } if (!ok) { return GL_FALSE; } LOCK_HARDWARE( mmesa ); #if 0 { __DRIdrawablePrivate *dPriv = mmesa->driDrawable; int nbox, retcode, i; UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); if (mmesa->dirty_cliprects & MGA_FRONT) mgaUpdateRects( mmesa, MGA_FRONT ); nbox = dPriv->numClipRects; y = dPriv->h - y - height; x += mmesa->drawX; y += mmesa->drawY; dest = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) | DO_dstmap_sys | DO_dstacc_agp); source_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp; dest_pitch = pitch; delta_sx = 0; delta_sy = 0; delta_dx = -x; delta_dy = -y; blit_height = 2*y + height; ydir = -1; if (0) fprintf(stderr, "XX doing readpixel blit src_pitch %d dst_pitch %d\n", source_pitch, dest_pitch); for (i = 0 ; i < nbox ; ) { int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); XF86DRIClipRectRec *box = dPriv->pClipRects; drm_clip_rect_t *b = mmesa->sarea->boxes; int n = 0; for ( ; i < nr ; i++) { GLint bx = box[i].x1; GLint by = box[i].y1; GLint bw = box[i].x2 - bx; GLint bh = box[i].y2 - by; if (bx < x) bw -= x - bx, bx = x; if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; if (bw <= 0) continue; if (bh <= 0) continue; b->x1 = bx; b->y1 = by; b->x2 = bx + bw; b->y2 = by + bh; b++; n++; } mmesa->sarea->nbox = n; if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT, &blit, sizeof(drmMGABlit)))) { fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode); UNLOCK_HARDWARE( mmesa ); exit(1); } } UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); } #endif UNLOCK_HARDWARE( mmesa ); return GL_TRUE; }