/* Called via glXGetMemoryOffsetMESA() */ GLuint r200GetMemoryOffsetMESA(__DRIscreen *screen, const GLvoid *pointer) { GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa; GLuint card_offset; if (!ctx || !(rmesa = R200_CONTEXT(ctx)) ) { fprintf(stderr, "%s: no context\n", __FUNCTION__); return ~0; } if (!r200IsGartMemory( rmesa, pointer, 0 )) return ~0; card_offset = r200GartOffsetFromVirtual( rmesa, pointer ); return card_offset - rmesa->radeon.radeonScreen->gart_base; }
/* Called via glXGetMemoryOffsetMESA() */ GLuint r200GetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn, const GLvoid *pointer) { GET_CURRENT_CONTEXT(ctx); r200ContextPtr rmesa; GLuint card_offset; if (!ctx || !(rmesa = R200_CONTEXT(ctx)) ) { fprintf(stderr, "%s: no context\n", __FUNCTION__); return ~0; } if (!r200IsGartMemory( rmesa, pointer, 0 )) return ~0; if (rmesa->dri.drmMinor < 6) return ~0; card_offset = r200GartOffsetFromVirtual( rmesa, pointer ); return card_offset - rmesa->r200Screen->gart_base; }
static GLboolean r200TryDrawPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); GLint pitch = unpack->RowLength ? unpack->RowLength : width; GLuint planemask; GLuint cpp = rmesa->r200Screen->cpp; GLint size = width * pitch * cpp; if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); /* check that we're drawing to exactly one color buffer */ if (ctx->DrawBuffer->_NumColorDrawBuffers[0] != 1) return GL_FALSE; switch (format) { case GL_RGB: case GL_RGBA: case GL_BGRA: planemask = r200PackColor(cpp, ctx->Color.ColorMask[RCOMP], ctx->Color.ColorMask[GCOMP], ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP]); if (cpp == 2) planemask |= planemask << 16; if (planemask != ~0) return GL_FALSE; /* fix me -- should be possible */ /* Can't do conversions on GART reads/draws. */ if ( !r200IsGartMemory( rmesa, pixels, size ) ) { if (R200_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s: not GART memory\n", __FUNCTION__); return GL_FALSE; } if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { return GL_FALSE; } if (!check_color_per_fragment_ops(ctx)) { return GL_FALSE; } if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != -1.0F) return GL_FALSE; break; default: return GL_FALSE; } if ( r200IsGartMemory(rmesa, pixels, size) ) { do_draw_pix( ctx, x, y, width, height, pitch, pixels, planemask ); return GL_TRUE; } else if (0) { /* Pixels is in regular memory -- get dma buffers and perform * upload through them. */ } else return GL_FALSE; }
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; }