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
);