static __DRIimage * radeon_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; radeonContextPtr radeon = context->driverPrivate; struct gl_renderbuffer *rb; struct radeon_renderbuffer *rrb; rb = _mesa_lookup_renderbuffer(&radeon->glCtx, renderbuffer); if (!rb) { _mesa_error(&radeon->glCtx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } rrb = radeon_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->cpp = rrb->cpp; image->data_type = GL_UNSIGNED_BYTE; image->data = loaderPrivate; radeon_bo_ref(rrb->bo); image->bo = rrb->bo; image->width = rb->Width; image->height = rb->Height; image->pitch = rrb->pitch / image->cpp; return image; }
static void radeon_renderbuffer_unmap(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); if (!rb || !rrb) return; ctx->Driver.UnmapRenderbuffer(ctx, rb); rrb->base.Map = NULL; rrb->base.RowStride = 0; }
static void radeon_delete_renderbuffer(struct gl_renderbuffer *rb) { struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(rb %p, rrb %p) \n", __func__, rb, rrb); ASSERT(rrb); if (rrb && rrb->bo) { radeon_bo_unref(rrb->bo); } free(rrb); }
static void radeon_renderbuffer_map(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); GLubyte *map; int stride; if (!rb || !rrb) return; ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &map, &stride); rrb->base.Map = map; rrb->base.RowStride = stride; /* No floating point color buffers, use GLubytes */ rrb->base.ColorType = GL_UNSIGNED_BYTE; }
static void radeon_image_target_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, void *image_handle) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_renderbuffer *rrb; __DRIscreen *screen; __DRIimage *image; screen = radeon->radeonScreen->driScreen; image = screen->dri2.image->lookupEGLImage(screen, image_handle, screen->loaderPrivate); if (image == NULL) return; rrb = radeon_renderbuffer(rb); if (ctx->Driver.Flush) ctx->Driver.Flush(ctx); /* +r6/r7 */ if (rrb->bo) radeon_bo_unref(rrb->bo); rrb->bo = image->bo; radeon_bo_ref(rrb->bo); fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle, image->width, image->pitch); rrb->cpp = image->cpp; rrb->pitch = image->pitch * image->cpp; rb->Format = image->format; rb->InternalFormat = image->internal_format; rb->Width = image->width; rb->Height = image->height; rb->Format = image->format; rb->DataType = image->data_type; rb->_BaseFormat = _mesa_base_fbo_format(radeon->glCtx, image->internal_format); }
static GLboolean do_blit_readpixels(struct gl_context * ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid * pixels) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type); unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y; struct radeon_bo *dst_buffer; GLint dst_x = 0, dst_y = 0; intptr_t dst_offset; /* It's not worth if number of pixels to copy is really small */ if (width * height < 100) { return GL_FALSE; } if (dst_format == MESA_FORMAT_NONE || !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) { return GL_FALSE; } if (ctx->_ImageTransferState || ctx->Color._LogicOpEnabled) { return GL_FALSE; } if (pack->SwapBytes || pack->LsbFirst) { return GL_FALSE; } if (pack->RowLength > 0) { dst_rowstride = pack->RowLength; } else { dst_rowstride = width; } if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { return GL_TRUE; } assert(x >= 0 && y >= 0); aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0); dst_rowstride *= _mesa_get_format_bytes(dst_format); if (_mesa_is_bufferobj(pack->BufferObj) && aligned_rowstride != dst_rowstride) return GL_FALSE; dst_imagesize = get_texture_image_size(dst_format, aligned_rowstride, height, 1, 0); if (!_mesa_is_bufferobj(pack->BufferObj)) { dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); dst_offset = 0; } else { dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo; dst_offset = (intptr_t)pixels; } /* Disable source Y flipping for FBOs */ flip_y = (ctx->ReadBuffer->Name == 0); if (pack->Invert) { y = rrb->base.Height - height - y; flip_y = !flip_y; } if (radeon->vtbl.blit(ctx, rrb->bo, rrb->draw_offset, rrb->base.Format, rrb->pitch / rrb->cpp, rrb->base.Width, rrb->base.Height, x, y, dst_buffer, dst_offset, dst_format, aligned_rowstride / _mesa_get_format_bytes(dst_format), width, height, 0, /* dst_x */ 0, /* dst_y */ width, height, flip_y)) { if (!_mesa_is_bufferobj(pack->BufferObj)) { radeon_bo_map(dst_buffer, 0); copy_rows(pixels, dst_rowstride, dst_buffer->ptr, aligned_rowstride, height, dst_rowstride); radeon_bo_unmap(dst_buffer); radeon_bo_unref(dst_buffer); } return GL_TRUE; } if (!_mesa_is_bufferobj(pack->BufferObj)) radeon_bo_unref(dst_buffer); return GL_FALSE; }
static GLboolean do_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, struct radeon_tex_obj *tobj, radeon_texture_image *timg, GLint dstx, GLint dsty, GLint x, GLint y, GLsizei width, GLsizei height) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_renderbuffer *rrb; unsigned src_bpp; unsigned dst_bpp; gl_format src_mesaformat; gl_format dst_mesaformat; unsigned src_width; unsigned dst_width; unsigned flip_y; if (!radeon->vtbl.blit) { return GL_FALSE; } if (_mesa_get_format_bits(timg->base.TexFormat, GL_DEPTH_BITS) > 0) { if (ctx->ReadBuffer->_DepthBuffer && ctx->ReadBuffer->_DepthBuffer->Wrapped) { rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer->Wrapped); } else { rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer); } flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE; } else { rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE; } // This is software renderbuffer, fallback to swrast if (!rrb) { return GL_FALSE; } if (!timg->mt) { radeon_validate_texture_miptree(ctx, &tobj->base); } assert(rrb->bo); assert(timg->mt); assert(timg->mt->bo); assert(timg->base.Width >= dstx + width); assert(timg->base.Height >= dsty + height); intptr_t src_offset = rrb->draw_offset; intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, _mesa_tex_target_to_face(target), level); if (0) { fprintf(stderr, "%s: copying to face %d, level %d\n", __FUNCTION__, _mesa_tex_target_to_face(target), level); fprintf(stderr, "to: x %d, y %d, offset %d\n", dstx, dsty, (uint32_t) dst_offset); fprintf(stderr, "from (%dx%d) width %d, height %d, offset %d, pitch %d\n", x, y, rrb->base.Width, rrb->base.Height, (uint32_t) src_offset, rrb->pitch/rrb->cpp); fprintf(stderr, "src size %d, dst size %d\n", rrb->bo->size, timg->mt->bo->size); } src_mesaformat = rrb->base.Format; dst_mesaformat = timg->base.TexFormat; src_width = rrb->base.Width; dst_width = timg->base.Width; src_bpp = _mesa_get_format_bytes(src_mesaformat); dst_bpp = _mesa_get_format_bytes(dst_mesaformat); if (!radeon->vtbl.check_blit(dst_mesaformat)) { /* depth formats tend to be special */ if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0) return GL_FALSE; if (src_bpp != dst_bpp) return GL_FALSE; switch (dst_bpp) { case 2: src_mesaformat = MESA_FORMAT_RGB565; dst_mesaformat = MESA_FORMAT_RGB565; break; case 4: src_mesaformat = MESA_FORMAT_ARGB8888; dst_mesaformat = MESA_FORMAT_ARGB8888; break; case 1: src_mesaformat = MESA_FORMAT_A8; dst_mesaformat = MESA_FORMAT_A8; break; default: return GL_FALSE; } } /* blit from src buffer to texture */ return radeon->vtbl.blit(ctx, rrb->bo, src_offset, src_mesaformat, rrb->pitch/rrb->cpp, src_width, rrb->base.Height, x, y, timg->mt->bo, dst_offset, dst_mesaformat, timg->mt->levels[level].rowstride / dst_bpp, dst_width, timg->base.Height, dstx, dsty, width, height, flip_y); }
/** * Called via glRenderbufferStorageEXT() to set the format and allocate * storage for a user-created renderbuffer. */ static GLboolean radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct radeon_context *radeon = RADEON_CONTEXT(ctx); struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); GLboolean software_buffer = GL_FALSE; int cpp; radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(%p, rb %p) \n", __func__, ctx, rb); ASSERT(rb->Name != 0); switch (internalFormat) { case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: rb->Format = _dri_texformat_rgb565; rb->DataType = GL_UNSIGNED_BYTE; cpp = 2; break; case GL_RGB: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: rb->Format = _dri_texformat_argb8888; rb->DataType = GL_UNSIGNED_BYTE; cpp = 4; break; case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: rb->Format = _dri_texformat_argb8888; rb->DataType = GL_UNSIGNED_BYTE; cpp = 4; break; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: /* alloc a depth+stencil buffer */ rb->Format = MESA_FORMAT_S8_Z24; rb->DataType = GL_UNSIGNED_INT_24_8_EXT; cpp = 4; break; case GL_DEPTH_COMPONENT16: rb->Format = MESA_FORMAT_Z16; rb->DataType = GL_UNSIGNED_SHORT; cpp = 2; break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: rb->Format = MESA_FORMAT_X8_Z24; rb->DataType = GL_UNSIGNED_INT; cpp = 4; break; case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: rb->Format = MESA_FORMAT_S8_Z24; rb->DataType = GL_UNSIGNED_INT_24_8_EXT; cpp = 4; break; default: _mesa_problem(ctx, "Unexpected format in radeon_alloc_renderbuffer_storage"); return GL_FALSE; } rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (ctx->Driver.Flush) ctx->Driver.Flush(ctx); /* +r6/r7 */ if (rrb->bo) radeon_bo_unref(rrb->bo); if (software_buffer) { return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, width, height); } else { uint32_t size; uint32_t pitch = ((cpp * width + 63) & ~63) / cpp; if (RADEON_DEBUG & RADEON_MEMORY) fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width, height, pitch); size = pitch * height * cpp; rrb->pitch = pitch * cpp; rrb->cpp = cpp; rrb->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); rb->Width = width; rb->Height = height; return GL_TRUE; } }
static void radeon_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer); radeon_texture_image *radeon_image; GLuint imageOffset; radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(%p, fb %p, rrb %p, att %p)\n", __func__, ctx, fb, rrb, att); (void) fb; ASSERT(newImage); radeon_image = (radeon_texture_image *)newImage; if (!radeon_image->mt || newImage->Border != 0) { /* Fallback on drawing to a texture without a miptree. */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } else if (!rrb) { rrb = radeon_wrap_texture(ctx, newImage); if (rrb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!radeon_update_wrapper(ctx, rrb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, rrb->base.RefCount); /* point the renderbufer's region to the texture image region */ if (rrb->bo != radeon_image->mt->bo) { if (rrb->bo) radeon_bo_unref(rrb->bo); rrb->bo = radeon_image->mt->bo; radeon_bo_ref(rrb->bo); } /* compute offset of the particular 2D image within the texture region */ imageOffset = radeon_miptree_image_offset(radeon_image->mt, att->CubeMapFace, att->TextureLevel); if (att->Texture->Target == GL_TEXTURE_3D) { imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride * radeon_image->mt->levels[att->TextureLevel].height * att->Zoffset; } /* store that offset in the region, along with the correct pitch for * the image we are rendering to */ rrb->draw_offset = imageOffset; rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride; /* update drawing region, etc */ radeon_draw_buffer(ctx, fb); }