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/mtypes.h"
32 #include "main/enums.h"
33 #include "main/fbobject.h"
34 #include "main/framebuffer.h"
35 #include "main/renderbuffer.h"
36 #include "main/context.h"
37 #include "main/texrender.h"
38 #include "drivers/common/meta.h"
40 #include "radeon_common.h"
41 #include "radeon_mipmap_tree.h"
43 #define FILE_DEBUG_FLAG RADEON_TEXTURE
44 #define DBG(...) do { \
45 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
46 _mesa_printf(__VA_ARGS__); \
49 static struct gl_framebuffer
*
50 radeon_new_framebuffer(GLcontext
*ctx
, GLuint name
)
52 return _mesa_new_framebuffer(ctx
, name
);
56 radeon_delete_renderbuffer(struct gl_renderbuffer
*rb
)
58 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(rb
);
60 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
61 "%s(rb %p, rrb %p) \n",
67 radeon_bo_unref(rrb
->bo
);
73 radeon_get_pointer(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
76 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
84 * Called via glRenderbufferStorageEXT() to set the format and allocate
85 * storage for a user-created renderbuffer.
88 radeon_alloc_renderbuffer_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
89 GLenum internalFormat
,
90 GLuint width
, GLuint height
)
92 struct radeon_context
*radeon
= RADEON_CONTEXT(ctx
);
93 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(rb
);
94 GLboolean software_buffer
= GL_FALSE
;
97 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
101 ASSERT(rb
->Name
!= 0);
102 switch (internalFormat
) {
106 rb
->Format
= _dri_texformat_rgb565
;
107 rb
->DataType
= GL_UNSIGNED_BYTE
;
115 rb
->Format
= _dri_texformat_argb8888
;
116 rb
->DataType
= GL_UNSIGNED_BYTE
;
127 rb
->Format
= _dri_texformat_argb8888
;
128 rb
->DataType
= GL_UNSIGNED_BYTE
;
131 case GL_STENCIL_INDEX
:
132 case GL_STENCIL_INDEX1_EXT
:
133 case GL_STENCIL_INDEX4_EXT
:
134 case GL_STENCIL_INDEX8_EXT
:
135 case GL_STENCIL_INDEX16_EXT
:
136 /* alloc a depth+stencil buffer */
137 rb
->Format
= MESA_FORMAT_S8_Z24
;
138 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
141 case GL_DEPTH_COMPONENT16
:
142 rb
->Format
= MESA_FORMAT_Z16
;
143 rb
->DataType
= GL_UNSIGNED_SHORT
;
146 case GL_DEPTH_COMPONENT
:
147 case GL_DEPTH_COMPONENT24
:
148 case GL_DEPTH_COMPONENT32
:
149 rb
->Format
= MESA_FORMAT_X8_Z24
;
150 rb
->DataType
= GL_UNSIGNED_INT
;
153 case GL_DEPTH_STENCIL_EXT
:
154 case GL_DEPTH24_STENCIL8_EXT
:
155 rb
->Format
= MESA_FORMAT_S8_Z24
;
156 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
161 "Unexpected format in radeon_alloc_renderbuffer_storage");
165 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
167 if (ctx
->Driver
.Flush
)
168 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
171 radeon_bo_unref(rrb
->bo
);
174 if (software_buffer
) {
175 return _mesa_soft_renderbuffer_storage(ctx
, rb
, internalFormat
,
180 uint32_t pitch
= ((cpp
* width
+ 63) & ~63) / cpp
;
182 if (RADEON_DEBUG
& RADEON_MEMORY
)
183 fprintf(stderr
,"Allocating %d x %d radeon RBO (pitch %d)\n", width
,
186 size
= pitch
* height
* cpp
;
187 rrb
->pitch
= pitch
* cpp
;
189 rrb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
193 RADEON_GEM_DOMAIN_VRAM
,
204 * Called for each hardware renderbuffer when a _window_ is resized.
205 * Just update fields.
206 * Not used for user-created renderbuffers!
209 radeon_alloc_window_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
210 GLenum internalFormat
, GLuint width
, GLuint height
)
212 ASSERT(rb
->Name
== 0);
215 rb
->InternalFormat
= internalFormat
;
216 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
226 radeon_resize_buffers(GLcontext
*ctx
, struct gl_framebuffer
*fb
,
227 GLuint width
, GLuint height
)
229 struct radeon_framebuffer
*radeon_fb
= (struct radeon_framebuffer
*)fb
;
232 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
236 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
238 fb
->Initialized
= GL_TRUE
; /* XXX remove someday */
244 /* Make sure all window system renderbuffers are up to date */
245 for (i
= 0; i
< 2; i
++) {
246 struct gl_renderbuffer
*rb
= &radeon_fb
->color_rb
[i
]->base
;
248 /* only resize if size is changing */
249 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
250 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
256 /** Dummy function for gl_renderbuffer::AllocStorage() */
258 radeon_nop_alloc_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
259 GLenum internalFormat
, GLuint width
, GLuint height
)
261 _mesa_problem(ctx
, "radeon_op_alloc_storage should never be called.");
267 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
268 * Not used for user-created renderbuffers.
270 struct radeon_renderbuffer
*
271 radeon_create_renderbuffer(gl_format format
, __DRIdrawable
*driDrawPriv
)
273 struct radeon_renderbuffer
*rrb
;
275 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
277 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
284 _mesa_init_renderbuffer(&rrb
->base
, 0);
285 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
287 rrb
->base
.Format
= format
;
290 case MESA_FORMAT_RGB565
:
291 assert(_mesa_little_endian());
292 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
293 rrb
->base
._BaseFormat
= GL_RGB
;
295 case MESA_FORMAT_RGB565_REV
:
296 assert(!_mesa_little_endian());
297 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
298 rrb
->base
._BaseFormat
= GL_RGB
;
300 case MESA_FORMAT_XRGB8888
:
301 assert(_mesa_little_endian());
302 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
303 rrb
->base
._BaseFormat
= GL_RGB
;
305 case MESA_FORMAT_XRGB8888_REV
:
306 assert(!_mesa_little_endian());
307 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
308 rrb
->base
._BaseFormat
= GL_RGB
;
310 case MESA_FORMAT_ARGB8888
:
311 assert(_mesa_little_endian());
312 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
313 rrb
->base
._BaseFormat
= GL_RGBA
;
315 case MESA_FORMAT_ARGB8888_REV
:
316 assert(!_mesa_little_endian());
317 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
318 rrb
->base
._BaseFormat
= GL_RGBA
;
321 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
322 rrb
->base
._BaseFormat
= GL_STENCIL_INDEX
;
324 case MESA_FORMAT_Z16
:
325 rrb
->base
.DataType
= GL_UNSIGNED_SHORT
;
326 rrb
->base
._BaseFormat
= GL_DEPTH_COMPONENT
;
328 case MESA_FORMAT_X8_Z24
:
329 rrb
->base
.DataType
= GL_UNSIGNED_INT
;
330 rrb
->base
._BaseFormat
= GL_DEPTH_COMPONENT
;
332 case MESA_FORMAT_S8_Z24
:
333 rrb
->base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
334 rrb
->base
._BaseFormat
= GL_DEPTH_STENCIL
;
337 fprintf(stderr
, "%s: Unknown format %s\n",
338 __FUNCTION__
, _mesa_get_format_name(format
));
339 _mesa_delete_renderbuffer(&rrb
->base
);
343 rrb
->dPriv
= driDrawPriv
;
344 rrb
->base
.InternalFormat
= _mesa_get_format_base_format(format
);
346 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
347 rrb
->base
.AllocStorage
= radeon_alloc_window_storage
;
348 rrb
->base
.GetPointer
= radeon_get_pointer
;
354 static struct gl_renderbuffer
*
355 radeon_new_renderbuffer(GLcontext
* ctx
, GLuint name
)
357 struct radeon_renderbuffer
*rrb
;
359 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
361 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
368 _mesa_init_renderbuffer(&rrb
->base
, name
);
369 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
371 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
372 rrb
->base
.AllocStorage
= radeon_alloc_renderbuffer_storage
;
373 rrb
->base
.GetPointer
= radeon_get_pointer
;
379 radeon_bind_framebuffer(GLcontext
* ctx
, GLenum target
,
380 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
382 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
383 "%s(%p, fb %p, target %s) \n",
385 _mesa_lookup_enum_by_nr(target
));
387 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
388 radeon_draw_buffer(ctx
, fb
);
391 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
396 radeon_framebuffer_renderbuffer(GLcontext
* ctx
,
397 struct gl_framebuffer
*fb
,
398 GLenum attachment
, struct gl_renderbuffer
*rb
)
401 if (ctx
->Driver
.Flush
)
402 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
404 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
405 "%s(%p, fb %p, rb %p) \n",
406 __func__
, ctx
, fb
, rb
);
408 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
409 radeon_draw_buffer(ctx
, fb
);
413 /* TODO: According to EXT_fbo spec internal format of texture image
414 * once set during glTexImage call, should be preserved when
415 * attaching image to renderbuffer. When HW doesn't support
416 * rendering to format of attached image, set framebuffer
417 * completeness accordingly in radeon_validate_framebuffer (issue #79).
420 radeon_update_wrapper(GLcontext
*ctx
, struct radeon_renderbuffer
*rrb
,
421 struct gl_texture_image
*texImage
)
426 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
427 "%s(%p, rrb %p, texImage %p) \n",
428 __func__
, ctx
, rrb
, texImage
);
431 if (texImage
->TexFormat
== _dri_texformat_argb8888
) {
432 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
433 DBG("Render to RGBA8 texture OK\n");
435 else if (texImage
->TexFormat
== _dri_texformat_rgb565
) {
436 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
437 DBG("Render to RGB5 texture OK\n");
439 else if (texImage
->TexFormat
== _dri_texformat_argb1555
) {
440 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
441 DBG("Render to ARGB1555 texture OK\n");
443 else if (texImage
->TexFormat
== _dri_texformat_argb4444
) {
444 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
445 DBG("Render to ARGB4444 texture OK\n");
447 else if (texImage
->TexFormat
== MESA_FORMAT_Z16
) {
448 rrb
->base
.DataType
= GL_UNSIGNED_SHORT
;
449 DBG("Render to DEPTH16 texture OK\n");
451 else if (texImage
->TexFormat
== MESA_FORMAT_S8_Z24
) {
452 rrb
->base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
453 DBG("Render to DEPTH_STENCIL texture OK\n");
456 /* try redoing the FBO */
458 DBG("Render to texture BAD FORMAT %d\n",
459 texImage
->TexFormat
);
462 /* XXX why is the tex format being set here?
463 * I think this can be removed.
465 texImage
->TexFormat
= radeonChooseTextureFormat(ctx
, texImage
->InternalFormat
, 0,
466 _mesa_get_format_datatype(texImage
->TexFormat
),
473 texFormat
= texImage
->TexFormat
;
475 rrb
->base
.Format
= texFormat
;
477 rrb
->cpp
= _mesa_get_format_bytes(texFormat
);
478 rrb
->pitch
= texImage
->Width
* rrb
->cpp
;
479 rrb
->base
.InternalFormat
= texImage
->InternalFormat
;
480 rrb
->base
._BaseFormat
= _mesa_base_fbo_format(ctx
, rrb
->base
.InternalFormat
);
482 rrb
->base
.Width
= texImage
->Width
;
483 rrb
->base
.Height
= texImage
->Height
;
485 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
486 rrb
->base
.AllocStorage
= radeon_nop_alloc_storage
;
492 static struct radeon_renderbuffer
*
493 radeon_wrap_texture(GLcontext
* ctx
, struct gl_texture_image
*texImage
)
495 const GLuint name
= ~0; /* not significant, but distinct for debugging */
496 struct radeon_renderbuffer
*rrb
;
498 /* make an radeon_renderbuffer to wrap the texture image */
499 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
501 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
502 "%s(%p, rrb %p, texImage %p) \n",
503 __func__
, ctx
, rrb
, texImage
);
506 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
510 _mesa_init_renderbuffer(&rrb
->base
, name
);
511 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
513 if (!radeon_update_wrapper(ctx
, rrb
, texImage
)) {
522 radeon_render_texture(GLcontext
* ctx
,
523 struct gl_framebuffer
*fb
,
524 struct gl_renderbuffer_attachment
*att
)
526 struct gl_texture_image
*newImage
527 = att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
528 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(att
->Renderbuffer
);
529 radeon_texture_image
*radeon_image
;
532 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
533 "%s(%p, fb %p, rrb %p, att %p)\n",
534 __func__
, ctx
, fb
, rrb
, att
);
540 if (newImage
->Border
!= 0) {
541 /* Fallback on drawing to a texture with a border, which won't have a
544 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
545 _mesa_render_texture(ctx
, fb
, att
);
549 rrb
= radeon_wrap_texture(ctx
, newImage
);
551 /* bind the wrapper to the attachment point */
552 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &rrb
->base
);
555 /* fallback to software rendering */
556 _mesa_render_texture(ctx
, fb
, att
);
561 if (!radeon_update_wrapper(ctx
, rrb
, newImage
)) {
562 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
563 _mesa_render_texture(ctx
, fb
, att
);
567 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
569 att
->Texture
->Name
, newImage
->Width
, newImage
->Height
,
572 /* point the renderbufer's region to the texture image region */
573 radeon_image
= (radeon_texture_image
*)newImage
;
574 if (rrb
->bo
!= radeon_image
->mt
->bo
) {
576 radeon_bo_unref(rrb
->bo
);
577 rrb
->bo
= radeon_image
->mt
->bo
;
578 radeon_bo_ref(rrb
->bo
);
581 /* compute offset of the particular 2D image within the texture region */
582 imageOffset
= radeon_miptree_image_offset(radeon_image
->mt
,
586 if (att
->Texture
->Target
== GL_TEXTURE_3D
) {
587 imageOffset
+= radeon_image
->mt
->levels
[att
->TextureLevel
].rowstride
*
588 radeon_image
->mt
->levels
[att
->TextureLevel
].height
*
592 /* store that offset in the region, along with the correct pitch for
593 * the image we are rendering to */
594 rrb
->draw_offset
= imageOffset
;
595 rrb
->pitch
= radeon_image
->mt
->levels
[att
->TextureLevel
].rowstride
;
597 /* update drawing region, etc */
598 radeon_draw_buffer(ctx
, fb
);
602 radeon_finish_render_texture(GLcontext
* ctx
,
603 struct gl_renderbuffer_attachment
*att
)
608 radeon_validate_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
612 void radeon_fbo_init(struct radeon_context
*radeon
)
614 radeon
->glCtx
->Driver
.NewFramebuffer
= radeon_new_framebuffer
;
615 radeon
->glCtx
->Driver
.NewRenderbuffer
= radeon_new_renderbuffer
;
616 radeon
->glCtx
->Driver
.BindFramebuffer
= radeon_bind_framebuffer
;
617 radeon
->glCtx
->Driver
.FramebufferRenderbuffer
= radeon_framebuffer_renderbuffer
;
618 radeon
->glCtx
->Driver
.RenderTexture
= radeon_render_texture
;
619 radeon
->glCtx
->Driver
.FinishRenderTexture
= radeon_finish_render_texture
;
620 radeon
->glCtx
->Driver
.ResizeBuffers
= radeon_resize_buffers
;
621 radeon
->glCtx
->Driver
.ValidateFramebuffer
= radeon_validate_framebuffer
;
622 radeon
->glCtx
->Driver
.BlitFramebuffer
= _mesa_meta_BlitFramebuffer
;
626 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer
*rb
,
627 struct radeon_bo
*bo
)
629 struct radeon_bo
*old
;
634 radeon_bo_unref(old
);