1 /**************************************************************************
3 * Copyright 2008 Red Hat Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 #include "main/imports.h"
30 #include "main/macros.h"
31 #include "main/mfeatures.h"
32 #include "main/mtypes.h"
33 #include "main/enums.h"
34 #include "main/fbobject.h"
35 #include "main/framebuffer.h"
36 #include "main/renderbuffer.h"
37 #include "main/context.h"
38 #include "swrast/swrast.h"
39 #include "drivers/common/meta.h"
41 #include "radeon_common.h"
42 #include "radeon_mipmap_tree.h"
44 #define FILE_DEBUG_FLAG RADEON_TEXTURE
45 #define DBG(...) do { \
46 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
47 printf(__VA_ARGS__); \
50 static struct gl_framebuffer *
51 radeon_new_framebuffer(struct gl_context *ctx, GLuint name)
53 return _mesa_new_framebuffer(ctx, name);
57 radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
59 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
61 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
62 "%s(rb %p, rrb %p) \n",
68 radeon_bo_unref(rrb->bo);
74 radeon_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb,
77 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
85 * Called via glRenderbufferStorageEXT() to set the format and allocate
86 * storage for a user-created renderbuffer.
89 radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
90 GLenum internalFormat,
91 GLuint width, GLuint height)
93 struct radeon_context *radeon = RADEON_CONTEXT(ctx);
94 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
95 GLboolean software_buffer = GL_FALSE;
98 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
102 ASSERT(rb->Name != 0);
103 switch (internalFormat) {
107 rb->Format = _dri_texformat_rgb565;
108 rb->DataType = GL_UNSIGNED_BYTE;
116 rb->Format = _dri_texformat_argb8888;
117 rb->DataType = GL_UNSIGNED_BYTE;
128 rb->Format = _dri_texformat_argb8888;
129 rb->DataType = GL_UNSIGNED_BYTE;
132 case GL_STENCIL_INDEX:
133 case GL_STENCIL_INDEX1_EXT:
134 case GL_STENCIL_INDEX4_EXT:
135 case GL_STENCIL_INDEX8_EXT:
136 case GL_STENCIL_INDEX16_EXT:
137 /* alloc a depth+stencil buffer */
138 rb->Format = MESA_FORMAT_S8_Z24;
139 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
142 case GL_DEPTH_COMPONENT16:
143 rb->Format = MESA_FORMAT_Z16;
144 rb->DataType = GL_UNSIGNED_SHORT;
147 case GL_DEPTH_COMPONENT:
148 case GL_DEPTH_COMPONENT24:
149 case GL_DEPTH_COMPONENT32:
150 rb->Format = MESA_FORMAT_X8_Z24;
151 rb->DataType = GL_UNSIGNED_INT;
154 case GL_DEPTH_STENCIL_EXT:
155 case GL_DEPTH24_STENCIL8_EXT:
156 rb->Format = MESA_FORMAT_S8_Z24;
157 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
162 "Unexpected format in radeon_alloc_renderbuffer_storage");
166 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
168 if (ctx->Driver.Flush)
169 ctx->Driver.Flush(ctx); /* +r6/r7 */
172 radeon_bo_unref(rrb->bo);
175 if (software_buffer) {
176 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
181 uint32_t pitch = ((cpp * width + 63) & ~63) / cpp;
183 if (RADEON_DEBUG & RADEON_MEMORY)
184 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
187 size = pitch * height * cpp;
188 rrb->pitch = pitch * cpp;
190 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
194 RADEON_GEM_DOMAIN_VRAM,
203 #if FEATURE_OES_EGL_image
205 radeon_image_target_renderbuffer_storage(struct gl_context *ctx,
206 struct gl_renderbuffer *rb,
209 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
210 struct radeon_renderbuffer *rrb;
214 screen = radeon->radeonScreen->driScreen;
215 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
216 screen->loaderPrivate);
220 rrb = radeon_renderbuffer(rb);
222 if (ctx->Driver.Flush)
223 ctx->Driver.Flush(ctx); /* +r6/r7 */
226 radeon_bo_unref(rrb->bo);
228 radeon_bo_ref(rrb->bo);
229 fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle,
230 image->width, image->pitch);
232 rrb->cpp = image->cpp;
233 rrb->pitch = image->pitch * image->cpp;
235 rb->Format = image->format;
236 rb->InternalFormat = image->internal_format;
237 rb->Width = image->width;
238 rb->Height = image->height;
239 rb->Format = image->format;
240 rb->DataType = image->data_type;
241 rb->_BaseFormat = _mesa_base_fbo_format(radeon->glCtx,
242 image->internal_format);
247 * Called for each hardware renderbuffer when a _window_ is resized.
248 * Just update fields.
249 * Not used for user-created renderbuffers!
252 radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
253 GLenum internalFormat, GLuint width, GLuint height)
255 ASSERT(rb->Name == 0);
258 rb->InternalFormat = internalFormat;
259 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
269 radeon_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
270 GLuint width, GLuint height)
272 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
275 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
279 _mesa_resize_framebuffer(ctx, fb, width, height);
281 fb->Initialized = GL_TRUE; /* XXX remove someday */
287 /* Make sure all window system renderbuffers are up to date */
288 for (i = 0; i < 2; i++) {
289 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
291 /* only resize if size is changing */
292 if (rb && (rb->Width != width || rb->Height != height)) {
293 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
299 /** Dummy function for gl_renderbuffer::AllocStorage() */
301 radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
302 GLenum internalFormat, GLuint width, GLuint height)
304 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
310 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
311 * Not used for user-created renderbuffers.
313 struct radeon_renderbuffer *
314 radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
316 struct radeon_renderbuffer *rrb;
318 rrb = CALLOC_STRUCT(radeon_renderbuffer);
320 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
327 _mesa_init_renderbuffer(&rrb->base, 0);
328 rrb->base.ClassID = RADEON_RB_CLASS;
330 rrb->base.Format = format;
333 case MESA_FORMAT_RGB565:
334 assert(_mesa_little_endian());
335 rrb->base.DataType = GL_UNSIGNED_BYTE;
336 rrb->base._BaseFormat = GL_RGB;
338 case MESA_FORMAT_RGB565_REV:
339 assert(!_mesa_little_endian());
340 rrb->base.DataType = GL_UNSIGNED_BYTE;
341 rrb->base._BaseFormat = GL_RGB;
343 case MESA_FORMAT_XRGB8888:
344 assert(_mesa_little_endian());
345 rrb->base.DataType = GL_UNSIGNED_BYTE;
346 rrb->base._BaseFormat = GL_RGB;
348 case MESA_FORMAT_XRGB8888_REV:
349 assert(!_mesa_little_endian());
350 rrb->base.DataType = GL_UNSIGNED_BYTE;
351 rrb->base._BaseFormat = GL_RGB;
353 case MESA_FORMAT_ARGB8888:
354 assert(_mesa_little_endian());
355 rrb->base.DataType = GL_UNSIGNED_BYTE;
356 rrb->base._BaseFormat = GL_RGBA;
358 case MESA_FORMAT_ARGB8888_REV:
359 assert(!_mesa_little_endian());
360 rrb->base.DataType = GL_UNSIGNED_BYTE;
361 rrb->base._BaseFormat = GL_RGBA;
364 rrb->base.DataType = GL_UNSIGNED_BYTE;
365 rrb->base._BaseFormat = GL_STENCIL_INDEX;
367 case MESA_FORMAT_Z16:
368 rrb->base.DataType = GL_UNSIGNED_SHORT;
369 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
371 case MESA_FORMAT_X8_Z24:
372 rrb->base.DataType = GL_UNSIGNED_INT;
373 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
375 case MESA_FORMAT_S8_Z24:
376 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
377 rrb->base._BaseFormat = GL_DEPTH_STENCIL;
380 fprintf(stderr, "%s: Unknown format %s\n",
381 __FUNCTION__, _mesa_get_format_name(format));
382 _mesa_delete_renderbuffer(&rrb->base);
386 rrb->dPriv = driDrawPriv;
387 rrb->base.InternalFormat = _mesa_get_format_base_format(format);
389 rrb->base.Delete = radeon_delete_renderbuffer;
390 rrb->base.AllocStorage = radeon_alloc_window_storage;
391 rrb->base.GetPointer = radeon_get_pointer;
397 static struct gl_renderbuffer *
398 radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
400 struct radeon_renderbuffer *rrb;
402 rrb = CALLOC_STRUCT(radeon_renderbuffer);
404 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
411 _mesa_init_renderbuffer(&rrb->base, name);
412 rrb->base.ClassID = RADEON_RB_CLASS;
414 rrb->base.Delete = radeon_delete_renderbuffer;
415 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
416 rrb->base.GetPointer = radeon_get_pointer;
422 radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
423 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
425 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
426 "%s(%p, fb %p, target %s) \n",
428 _mesa_lookup_enum_by_nr(target));
430 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
431 radeon_draw_buffer(ctx, fb);
434 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
439 radeon_framebuffer_renderbuffer(struct gl_context * ctx,
440 struct gl_framebuffer *fb,
441 GLenum attachment, struct gl_renderbuffer *rb)
444 if (ctx->Driver.Flush)
445 ctx->Driver.Flush(ctx); /* +r6/r7 */
447 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
448 "%s(%p, fb %p, rb %p) \n",
449 __func__, ctx, fb, rb);
451 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
452 radeon_draw_buffer(ctx, fb);
456 radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
457 struct gl_texture_image *texImage)
459 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
460 "%s(%p, rrb %p, texImage %p, texFormat %s) \n",
461 __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
463 switch (texImage->TexFormat) {
464 case MESA_FORMAT_RGBA8888:
465 case MESA_FORMAT_RGBA8888_REV:
466 case MESA_FORMAT_ARGB8888:
467 case MESA_FORMAT_ARGB8888_REV:
468 case MESA_FORMAT_XRGB8888:
469 case MESA_FORMAT_XRGB8888_REV:
470 case MESA_FORMAT_RGB565:
471 case MESA_FORMAT_RGB565_REV:
472 case MESA_FORMAT_RGBA5551:
473 case MESA_FORMAT_ARGB1555:
474 case MESA_FORMAT_ARGB1555_REV:
475 case MESA_FORMAT_ARGB4444:
476 case MESA_FORMAT_ARGB4444_REV:
477 rrb->base.DataType = GL_UNSIGNED_BYTE;
479 case MESA_FORMAT_Z16:
480 rrb->base.DataType = GL_UNSIGNED_SHORT;
482 case MESA_FORMAT_X8_Z24:
483 rrb->base.DataType = GL_UNSIGNED_INT;
485 case MESA_FORMAT_S8_Z24:
486 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
489 _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()");
492 rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
493 rrb->pitch = texImage->Width * rrb->cpp;
494 rrb->base.Format = texImage->TexFormat;
495 rrb->base.InternalFormat = texImage->InternalFormat;
496 rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat);
497 rrb->base.Width = texImage->Width;
498 rrb->base.Height = texImage->Height;
499 rrb->base.Delete = radeon_delete_renderbuffer;
500 rrb->base.AllocStorage = radeon_nop_alloc_storage;
506 static struct radeon_renderbuffer *
507 radeon_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
509 const GLuint name = ~0; /* not significant, but distinct for debugging */
510 struct radeon_renderbuffer *rrb;
512 /* make an radeon_renderbuffer to wrap the texture image */
513 rrb = CALLOC_STRUCT(radeon_renderbuffer);
515 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
516 "%s(%p, rrb %p, texImage %p) \n",
517 __func__, ctx, rrb, texImage);
520 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
524 _mesa_init_renderbuffer(&rrb->base, name);
525 rrb->base.ClassID = RADEON_RB_CLASS;
527 if (!radeon_update_wrapper(ctx, rrb, texImage)) {
536 radeon_render_texture(struct gl_context * ctx,
537 struct gl_framebuffer *fb,
538 struct gl_renderbuffer_attachment *att)
540 struct gl_texture_image *newImage
541 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
542 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
543 radeon_texture_image *radeon_image;
546 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
547 "%s(%p, fb %p, rrb %p, att %p)\n",
548 __func__, ctx, fb, rrb, att);
554 radeon_image = (radeon_texture_image *)newImage;
556 if (!radeon_image->mt || newImage->Border != 0) {
557 /* Fallback on drawing to a texture without a miptree.
559 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
560 _swrast_render_texture(ctx, fb, att);
564 rrb = radeon_wrap_texture(ctx, newImage);
566 /* bind the wrapper to the attachment point */
567 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
570 /* fallback to software rendering */
571 _swrast_render_texture(ctx, fb, att);
576 if (!radeon_update_wrapper(ctx, rrb, newImage)) {
577 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
578 _swrast_render_texture(ctx, fb, att);
582 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
584 att->Texture->Name, newImage->Width, newImage->Height,
587 /* point the renderbufer's region to the texture image region */
588 if (rrb->bo != radeon_image->mt->bo) {
590 radeon_bo_unref(rrb->bo);
591 rrb->bo = radeon_image->mt->bo;
592 radeon_bo_ref(rrb->bo);
595 /* compute offset of the particular 2D image within the texture region */
596 imageOffset = radeon_miptree_image_offset(radeon_image->mt,
600 if (att->Texture->Target == GL_TEXTURE_3D) {
601 imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
602 radeon_image->mt->levels[att->TextureLevel].height *
606 /* store that offset in the region, along with the correct pitch for
607 * the image we are rendering to */
608 rrb->draw_offset = imageOffset;
609 rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
611 /* update drawing region, etc */
612 radeon_draw_buffer(ctx, fb);
616 radeon_finish_render_texture(struct gl_context * ctx,
617 struct gl_renderbuffer_attachment *att)
622 radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
624 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
625 gl_format mesa_format;
628 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
629 struct gl_renderbuffer_attachment *att;
631 att = &fb->Attachment[BUFFER_DEPTH];
632 } else if (i == -1) {
633 att = &fb->Attachment[BUFFER_STENCIL];
635 att = &fb->Attachment[BUFFER_COLOR0 + i];
638 if (att->Type == GL_TEXTURE) {
639 mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat;
641 /* All renderbuffer formats are renderable, but not sampable */
645 if (!radeon->vtbl.is_format_renderable(mesa_format)){
646 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
647 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
648 "%s: HW doesn't support format %s as output format of attachment %d\n",
649 __FUNCTION__, _mesa_get_format_name(mesa_format), i);
655 void radeon_fbo_init(struct radeon_context *radeon)
657 #if FEATURE_EXT_framebuffer_object
658 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
659 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
660 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
661 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
662 radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
663 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
664 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
665 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
667 #if FEATURE_EXT_framebuffer_blit
668 radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
670 #if FEATURE_OES_EGL_image
671 radeon->glCtx->Driver.EGLImageTargetRenderbufferStorage =
672 radeon_image_target_renderbuffer_storage;
677 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
678 struct radeon_bo *bo)
680 struct radeon_bo *old;
685 radeon_bo_unref(old);