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/fbobject.h"
33 #include "main/framebuffer.h"
34 #include "main/renderbuffer.h"
35 #include "main/context.h"
36 #include "main/texformat.h"
37 #include "main/texrender.h"
39 #include "radeon_common.h"
40 #include "radeon_mipmap_tree.h"
42 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
43 #define DBG(...) do { \
44 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
45 _mesa_printf(__VA_ARGS__); \
48 static struct gl_framebuffer
*
49 radeon_new_framebuffer(GLcontext
*ctx
, GLuint name
)
51 return _mesa_new_framebuffer(ctx
, name
);
55 radeon_delete_renderbuffer(struct gl_renderbuffer
*rb
)
57 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(rb
);
62 radeon_bo_unref(rrb
->bo
);
68 radeon_get_pointer(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
75 * Called via glRenderbufferStorageEXT() to set the format and allocate
76 * storage for a user-created renderbuffer.
79 radeon_alloc_renderbuffer_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
80 GLenum internalFormat
,
81 GLuint width
, GLuint height
)
83 struct radeon_context
*radeon
= RADEON_CONTEXT(ctx
);
84 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(rb
);
85 GLboolean software_buffer
= GL_FALSE
;
88 ASSERT(rb
->Name
!= 0);
89 switch (internalFormat
) {
93 rb
->_ActualFormat
= GL_RGB5
;
94 rb
->DataType
= GL_UNSIGNED_BYTE
;
105 rb
->_ActualFormat
= GL_RGB8
;
106 rb
->DataType
= GL_UNSIGNED_BYTE
;
121 rb
->_ActualFormat
= GL_RGBA8
;
122 rb
->DataType
= GL_UNSIGNED_BYTE
;
129 case GL_STENCIL_INDEX
:
130 case GL_STENCIL_INDEX1_EXT
:
131 case GL_STENCIL_INDEX4_EXT
:
132 case GL_STENCIL_INDEX8_EXT
:
133 case GL_STENCIL_INDEX16_EXT
:
134 /* alloc a depth+stencil buffer */
135 rb
->_ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
136 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
140 case GL_DEPTH_COMPONENT16
:
141 rb
->_ActualFormat
= GL_DEPTH_COMPONENT16
;
142 rb
->DataType
= GL_UNSIGNED_SHORT
;
146 case GL_DEPTH_COMPONENT
:
147 case GL_DEPTH_COMPONENT24
:
148 case GL_DEPTH_COMPONENT32
:
149 rb
->_ActualFormat
= GL_DEPTH_COMPONENT24
;
150 rb
->DataType
= GL_UNSIGNED_INT
;
154 case GL_DEPTH_STENCIL_EXT
:
155 case GL_DEPTH24_STENCIL8_EXT
:
156 rb
->_ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
157 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
164 "Unexpected format in intel_alloc_renderbuffer_storage");
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
,
180 uint32_t size
= width
* height
* cpp
;
181 uint32_t pitch
= ((cpp
* width
+ 63) & ~63) / cpp
;
183 fprintf(stderr
,"Allocating %d x %d radeon RBO (pitch %d)\n", width
,
186 rrb
->pitch
= pitch
* cpp
;
188 rrb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
192 RADEON_GEM_DOMAIN_VRAM
,
203 * Called for each hardware renderbuffer when a _window_ is resized.
204 * Just update fields.
205 * Not used for user-created renderbuffers!
208 radeon_alloc_window_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
209 GLenum internalFormat
, GLuint width
, GLuint height
)
211 ASSERT(rb
->Name
== 0);
214 rb
->_ActualFormat
= internalFormat
;
221 radeon_resize_buffers(GLcontext
*ctx
, struct gl_framebuffer
*fb
,
222 GLuint width
, GLuint height
)
224 struct radeon_framebuffer
*radeon_fb
= (struct radeon_framebuffer
*)fb
;
227 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
229 fb
->Initialized
= GL_TRUE
; /* XXX remove someday */
235 /* Make sure all window system renderbuffers are up to date */
236 for (i
= 0; i
< 2; i
++) {
237 struct gl_renderbuffer
*rb
= &radeon_fb
->color_rb
[i
]->base
;
239 /* only resize if size is changing */
240 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
241 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
247 /** Dummy function for gl_renderbuffer::AllocStorage() */
249 radeon_nop_alloc_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
250 GLenum internalFormat
, GLuint width
, GLuint height
)
252 _mesa_problem(ctx
, "radeon_op_alloc_storage should never be called.");
256 struct radeon_renderbuffer
*
257 radeon_create_renderbuffer(GLenum format
, __DRIdrawablePrivate
*driDrawPriv
)
259 struct radeon_renderbuffer
*rrb
;
261 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
265 _mesa_init_renderbuffer(&rrb
->base
, 0);
266 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
268 /* XXX format junk */
271 rrb
->base
._ActualFormat
= GL_RGB5
;
272 rrb
->base
._BaseFormat
= GL_RGBA
;
273 rrb
->base
.RedBits
= 5;
274 rrb
->base
.GreenBits
= 6;
275 rrb
->base
.BlueBits
= 5;
276 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
279 rrb
->base
._ActualFormat
= GL_RGB8
;
280 rrb
->base
._BaseFormat
= GL_RGB
;
281 rrb
->base
.RedBits
= 8;
282 rrb
->base
.GreenBits
= 8;
283 rrb
->base
.BlueBits
= 8;
284 rrb
->base
.AlphaBits
= 0;
285 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
288 rrb
->base
._ActualFormat
= GL_RGBA8
;
289 rrb
->base
._BaseFormat
= GL_RGBA
;
290 rrb
->base
.RedBits
= 8;
291 rrb
->base
.GreenBits
= 8;
292 rrb
->base
.BlueBits
= 8;
293 rrb
->base
.AlphaBits
= 8;
294 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
296 case GL_STENCIL_INDEX8_EXT
:
297 rrb
->base
._ActualFormat
= GL_STENCIL_INDEX8_EXT
;
298 rrb
->base
._BaseFormat
= GL_STENCIL_INDEX
;
299 rrb
->base
.StencilBits
= 8;
300 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
302 case GL_DEPTH_COMPONENT16
:
303 rrb
->base
._ActualFormat
= GL_DEPTH_COMPONENT16
;
304 rrb
->base
._BaseFormat
= GL_DEPTH_COMPONENT
;
305 rrb
->base
.DepthBits
= 16;
306 rrb
->base
.DataType
= GL_UNSIGNED_SHORT
;
308 case GL_DEPTH_COMPONENT24
:
309 rrb
->base
._ActualFormat
= GL_DEPTH_COMPONENT24
;
310 rrb
->base
._BaseFormat
= GL_DEPTH_COMPONENT
;
311 rrb
->base
.DepthBits
= 24;
312 rrb
->base
.DataType
= GL_UNSIGNED_INT
;
314 case GL_DEPTH24_STENCIL8_EXT
:
315 rrb
->base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
316 rrb
->base
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
317 rrb
->base
.DepthBits
= 24;
318 rrb
->base
.StencilBits
= 8;
319 rrb
->base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
322 fprintf(stderr
, "%s: Unknown format 0x%04x\n", __FUNCTION__
, format
);
323 _mesa_delete_renderbuffer(&rrb
->base
);
327 rrb
->dPriv
= driDrawPriv
;
328 rrb
->base
.InternalFormat
= format
;
330 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
331 rrb
->base
.AllocStorage
= radeon_alloc_window_storage
;
332 rrb
->base
.GetPointer
= radeon_get_pointer
;
338 static struct gl_renderbuffer
*
339 radeon_new_renderbuffer(GLcontext
* ctx
, GLuint name
)
341 struct radeon_renderbuffer
*rrb
;
343 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
347 _mesa_init_renderbuffer(&rrb
->base
, name
);
348 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
350 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
351 rrb
->base
.AllocStorage
= radeon_alloc_renderbuffer_storage
;
352 rrb
->base
.GetPointer
= radeon_get_pointer
;
358 radeon_bind_framebuffer(GLcontext
* ctx
, GLenum target
,
359 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
361 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
362 radeon_draw_buffer(ctx
, fb
);
365 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
370 radeon_framebuffer_renderbuffer(GLcontext
* ctx
,
371 struct gl_framebuffer
*fb
,
372 GLenum attachment
, struct gl_renderbuffer
*rb
)
375 if (ctx
->Driver
.Flush
)
376 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
378 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
379 radeon_draw_buffer(ctx
, fb
);
384 radeon_update_wrapper(GLcontext
*ctx
, struct radeon_renderbuffer
*rrb
,
385 struct gl_texture_image
*texImage
)
389 if (texImage
->TexFormat
== &_mesa_texformat_argb8888
) {
391 rrb
->base
._ActualFormat
= GL_RGBA8
;
392 rrb
->base
._BaseFormat
= GL_RGBA
;
393 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
394 DBG("Render to RGBA8 texture OK\n");
396 else if (texImage
->TexFormat
== &_mesa_texformat_rgb565
) {
398 rrb
->base
._ActualFormat
= GL_RGB5
;
399 rrb
->base
._BaseFormat
= GL_RGB
;
400 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
401 DBG("Render to RGB5 texture OK\n");
403 else if (texImage
->TexFormat
== &_mesa_texformat_argb1555
) {
405 rrb
->base
._ActualFormat
= GL_RGB5_A1
;
406 rrb
->base
._BaseFormat
= GL_RGBA
;
407 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
408 DBG("Render to ARGB1555 texture OK\n");
410 else if (texImage
->TexFormat
== &_mesa_texformat_argb4444
) {
412 rrb
->base
._ActualFormat
= GL_RGBA4
;
413 rrb
->base
._BaseFormat
= GL_RGBA
;
414 rrb
->base
.DataType
= GL_UNSIGNED_BYTE
;
415 DBG("Render to ARGB1555 texture OK\n");
417 else if (texImage
->TexFormat
== &_mesa_texformat_z16
) {
419 rrb
->base
._ActualFormat
= GL_DEPTH_COMPONENT16
;
420 rrb
->base
._BaseFormat
= GL_DEPTH_COMPONENT
;
421 rrb
->base
.DataType
= GL_UNSIGNED_SHORT
;
422 DBG("Render to DEPTH16 texture OK\n");
424 else if (texImage
->TexFormat
== &_mesa_texformat_s8_z24
) {
426 rrb
->base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
427 rrb
->base
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
428 rrb
->base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
429 DBG("Render to DEPTH_STENCIL texture OK\n");
432 /* try redoing the FBO */
434 DBG("Render to texture BAD FORMAT %d\n",
435 texImage
->TexFormat
->MesaFormat
);
438 texImage
->TexFormat
= radeonChooseTextureFormat(ctx
, texImage
->InternalFormat
, 0,
439 texImage
->TexFormat
->DataType
,
446 rrb
->pitch
= texImage
->Width
* rrb
->cpp
;
447 rrb
->base
.InternalFormat
= rrb
->base
._ActualFormat
;
448 rrb
->base
.Width
= texImage
->Width
;
449 rrb
->base
.Height
= texImage
->Height
;
450 rrb
->base
.RedBits
= texImage
->TexFormat
->RedBits
;
451 rrb
->base
.GreenBits
= texImage
->TexFormat
->GreenBits
;
452 rrb
->base
.BlueBits
= texImage
->TexFormat
->BlueBits
;
453 rrb
->base
.AlphaBits
= texImage
->TexFormat
->AlphaBits
;
454 rrb
->base
.DepthBits
= texImage
->TexFormat
->DepthBits
;
455 rrb
->base
.StencilBits
= texImage
->TexFormat
->StencilBits
;
457 rrb
->base
.Delete
= radeon_delete_renderbuffer
;
458 rrb
->base
.AllocStorage
= radeon_nop_alloc_storage
;
464 static struct radeon_renderbuffer
*
465 radeon_wrap_texture(GLcontext
* ctx
, struct gl_texture_image
*texImage
)
467 const GLuint name
= ~0; /* not significant, but distinct for debugging */
468 struct radeon_renderbuffer
*rrb
;
470 /* make an radeon_renderbuffer to wrap the texture image */
471 rrb
= CALLOC_STRUCT(radeon_renderbuffer
);
473 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
477 _mesa_init_renderbuffer(&rrb
->base
, name
);
478 rrb
->base
.ClassID
= RADEON_RB_CLASS
;
480 if (!radeon_update_wrapper(ctx
, rrb
, texImage
)) {
489 radeon_render_texture(GLcontext
* ctx
,
490 struct gl_framebuffer
*fb
,
491 struct gl_renderbuffer_attachment
*att
)
493 struct gl_texture_image
*newImage
494 = att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
495 struct radeon_renderbuffer
*rrb
= radeon_renderbuffer(att
->Renderbuffer
);
496 radeon_texture_image
*radeon_image
;
503 if (newImage
->Border
!= 0) {
504 /* Fallback on drawing to a texture with a border, which won't have a
507 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
508 _mesa_render_texture(ctx
, fb
, att
);
512 rrb
= radeon_wrap_texture(ctx
, newImage
);
514 /* bind the wrapper to the attachment point */
515 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &rrb
->base
);
518 /* fallback to software rendering */
519 _mesa_render_texture(ctx
, fb
, att
);
524 if (!radeon_update_wrapper(ctx
, rrb
, newImage
)) {
525 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
526 _mesa_render_texture(ctx
, fb
, att
);
530 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
532 att
->Texture
->Name
, newImage
->Width
, newImage
->Height
,
535 /* point the renderbufer's region to the texture image region */
536 radeon_image
= (radeon_texture_image
*)newImage
;
537 if (rrb
->bo
!= radeon_image
->mt
->bo
) {
539 radeon_bo_unref(rrb
->bo
);
540 rrb
->bo
= radeon_image
->mt
->bo
;
541 radeon_bo_ref(rrb
->bo
);
544 /* compute offset of the particular 2D image within the texture region */
545 imageOffset
= radeon_miptree_image_offset(radeon_image
->mt
,
549 if (att
->Texture
->Target
== GL_TEXTURE_3D
) {
551 radeon_miptree_depth_offsets(radeon_image
->mt
, att
->TextureLevel
,
553 imageOffset
+= offsets
[att
->Zoffset
];
556 /* store that offset in the region */
557 rrb
->draw_offset
= imageOffset
;
559 /* update drawing region, etc */
560 radeon_draw_buffer(ctx
, fb
);
564 radeon_finish_render_texture(GLcontext
* ctx
,
565 struct gl_renderbuffer_attachment
*att
)
570 radeon_validate_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
575 radeon_blit_framebuffer(GLcontext
*ctx
,
576 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
577 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
578 GLbitfield mask
, GLenum filter
)
582 void radeon_fbo_init(struct radeon_context
*radeon
)
584 radeon
->glCtx
->Driver
.NewFramebuffer
= radeon_new_framebuffer
;
585 radeon
->glCtx
->Driver
.NewRenderbuffer
= radeon_new_renderbuffer
;
586 radeon
->glCtx
->Driver
.BindFramebuffer
= radeon_bind_framebuffer
;
587 radeon
->glCtx
->Driver
.FramebufferRenderbuffer
= radeon_framebuffer_renderbuffer
;
588 radeon
->glCtx
->Driver
.RenderTexture
= radeon_render_texture
;
589 radeon
->glCtx
->Driver
.FinishRenderTexture
= radeon_finish_render_texture
;
590 radeon
->glCtx
->Driver
.ResizeBuffers
= radeon_resize_buffers
;
591 radeon
->glCtx
->Driver
.ValidateFramebuffer
= radeon_validate_framebuffer
;
592 radeon
->glCtx
->Driver
.BlitFramebuffer
= radeon_blit_framebuffer
;
596 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer
*rb
,
597 struct radeon_bo
*bo
)
599 struct radeon_bo
*old
;
604 radeon_bo_unref(old
);