a8931e8478d38c8f37d1dcf052debc2e2057c553
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_fbo.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Red Hat Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
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"
39
40 #include "radeon_common.h"
41 #include "radeon_mipmap_tree.h"
42
43 #define FILE_DEBUG_FLAG RADEON_TEXTURE
44 #define DBG(...) do { \
45 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
46 _mesa_printf(__VA_ARGS__); \
47 } while(0)
48
49 static struct gl_framebuffer *
50 radeon_new_framebuffer(GLcontext *ctx, GLuint name)
51 {
52 return _mesa_new_framebuffer(ctx, name);
53 }
54
55 static void
56 radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
57 {
58 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
59
60 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
61 "%s(rb %p, rrb %p) \n",
62 __func__, rb, rrb);
63
64 ASSERT(rrb);
65
66 if (rrb && rrb->bo) {
67 radeon_bo_unref(rrb->bo);
68 }
69 free(rrb);
70 }
71
72 static void *
73 radeon_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
74 GLint x, GLint y)
75 {
76 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
77 "%s(%p, rb %p) \n",
78 __func__, ctx, rb);
79
80 return NULL;
81 }
82
83 /**
84 * Called via glRenderbufferStorageEXT() to set the format and allocate
85 * storage for a user-created renderbuffer.
86 */
87 static GLboolean
88 radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
89 GLenum internalFormat,
90 GLuint width, GLuint height)
91 {
92 struct radeon_context *radeon = RADEON_CONTEXT(ctx);
93 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
94 GLboolean software_buffer = GL_FALSE;
95 int cpp;
96
97 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
98 "%s(%p, rb %p) \n",
99 __func__, ctx, rb);
100
101 ASSERT(rb->Name != 0);
102 switch (internalFormat) {
103 case GL_R3_G3_B2:
104 case GL_RGB4:
105 case GL_RGB5:
106 rb->Format = _dri_texformat_rgb565;
107 rb->DataType = GL_UNSIGNED_BYTE;
108 cpp = 2;
109 break;
110 case GL_RGB:
111 case GL_RGB8:
112 case GL_RGB10:
113 case GL_RGB12:
114 case GL_RGB16:
115 rb->Format = _dri_texformat_argb8888;
116 rb->DataType = GL_UNSIGNED_BYTE;
117 cpp = 4;
118 break;
119 case GL_RGBA:
120 case GL_RGBA2:
121 case GL_RGBA4:
122 case GL_RGB5_A1:
123 case GL_RGBA8:
124 case GL_RGB10_A2:
125 case GL_RGBA12:
126 case GL_RGBA16:
127 rb->Format = _dri_texformat_argb8888;
128 rb->DataType = GL_UNSIGNED_BYTE;
129 cpp = 4;
130 break;
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;
139 cpp = 4;
140 break;
141 case GL_DEPTH_COMPONENT16:
142 rb->Format = MESA_FORMAT_Z16;
143 rb->DataType = GL_UNSIGNED_SHORT;
144 cpp = 2;
145 break;
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;
151 cpp = 4;
152 break;
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;
157 cpp = 4;
158 break;
159 default:
160 _mesa_problem(ctx,
161 "Unexpected format in radeon_alloc_renderbuffer_storage");
162 return GL_FALSE;
163 }
164
165 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
166
167 if (ctx->Driver.Flush)
168 ctx->Driver.Flush(ctx); /* +r6/r7 */
169
170 if (rrb->bo)
171 radeon_bo_unref(rrb->bo);
172
173
174 if (software_buffer) {
175 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
176 width, height);
177 }
178 else {
179 uint32_t size;
180 uint32_t pitch = ((cpp * width + 63) & ~63) / cpp;
181
182 if (RADEON_DEBUG & RADEON_MEMORY)
183 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
184 height, pitch);
185
186 size = pitch * height * cpp;
187 rrb->pitch = pitch * cpp;
188 rrb->cpp = cpp;
189 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
190 0,
191 size,
192 0,
193 RADEON_GEM_DOMAIN_VRAM,
194 0);
195 rb->Width = width;
196 rb->Height = height;
197 return GL_TRUE;
198 }
199
200 }
201
202
203 /**
204 * Called for each hardware renderbuffer when a _window_ is resized.
205 * Just update fields.
206 * Not used for user-created renderbuffers!
207 */
208 static GLboolean
209 radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
210 GLenum internalFormat, GLuint width, GLuint height)
211 {
212 ASSERT(rb->Name == 0);
213 rb->Width = width;
214 rb->Height = height;
215 rb->InternalFormat = internalFormat;
216 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
217 "%s(%p, rb %p) \n",
218 __func__, ctx, rb);
219
220
221 return GL_TRUE;
222 }
223
224
225 static void
226 radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
227 GLuint width, GLuint height)
228 {
229 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
230 int i;
231
232 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
233 "%s(%p, fb %p) \n",
234 __func__, ctx, fb);
235
236 _mesa_resize_framebuffer(ctx, fb, width, height);
237
238 fb->Initialized = GL_TRUE; /* XXX remove someday */
239
240 if (fb->Name != 0) {
241 return;
242 }
243
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;
247
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);
251 }
252 }
253 }
254
255
256 /** Dummy function for gl_renderbuffer::AllocStorage() */
257 static GLboolean
258 radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
259 GLenum internalFormat, GLuint width, GLuint height)
260 {
261 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
262 return GL_FALSE;
263 }
264
265
266 /**
267 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
268 * Not used for user-created renderbuffers.
269 */
270 struct radeon_renderbuffer *
271 radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
272 {
273 struct radeon_renderbuffer *rrb;
274
275 rrb = CALLOC_STRUCT(radeon_renderbuffer);
276
277 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
278 "%s( rrb %p ) \n",
279 __func__, rrb);
280
281 if (!rrb)
282 return NULL;
283
284 _mesa_init_renderbuffer(&rrb->base, 0);
285 rrb->base.ClassID = RADEON_RB_CLASS;
286
287 rrb->base.Format = format;
288
289 switch (format) {
290 case MESA_FORMAT_RGB565:
291 assert(_mesa_little_endian());
292 rrb->base.DataType = GL_UNSIGNED_BYTE;
293 rrb->base._BaseFormat = GL_RGB;
294 break;
295 case MESA_FORMAT_RGB565_REV:
296 assert(!_mesa_little_endian());
297 rrb->base.DataType = GL_UNSIGNED_BYTE;
298 rrb->base._BaseFormat = GL_RGB;
299 break;
300 case MESA_FORMAT_XRGB8888:
301 assert(_mesa_little_endian());
302 rrb->base.DataType = GL_UNSIGNED_BYTE;
303 rrb->base._BaseFormat = GL_RGB;
304 break;
305 case MESA_FORMAT_XRGB8888_REV:
306 assert(!_mesa_little_endian());
307 rrb->base.DataType = GL_UNSIGNED_BYTE;
308 rrb->base._BaseFormat = GL_RGB;
309 break;
310 case MESA_FORMAT_ARGB8888:
311 assert(_mesa_little_endian());
312 rrb->base.DataType = GL_UNSIGNED_BYTE;
313 rrb->base._BaseFormat = GL_RGBA;
314 break;
315 case MESA_FORMAT_ARGB8888_REV:
316 assert(!_mesa_little_endian());
317 rrb->base.DataType = GL_UNSIGNED_BYTE;
318 rrb->base._BaseFormat = GL_RGBA;
319 break;
320 case MESA_FORMAT_S8:
321 rrb->base.DataType = GL_UNSIGNED_BYTE;
322 rrb->base._BaseFormat = GL_STENCIL_INDEX;
323 break;
324 case MESA_FORMAT_Z16:
325 rrb->base.DataType = GL_UNSIGNED_SHORT;
326 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
327 break;
328 case MESA_FORMAT_X8_Z24:
329 rrb->base.DataType = GL_UNSIGNED_INT;
330 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
331 break;
332 case MESA_FORMAT_S8_Z24:
333 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
334 rrb->base._BaseFormat = GL_DEPTH_STENCIL;
335 break;
336 default:
337 fprintf(stderr, "%s: Unknown format %s\n",
338 __FUNCTION__, _mesa_get_format_name(format));
339 _mesa_delete_renderbuffer(&rrb->base);
340 return NULL;
341 }
342
343 rrb->dPriv = driDrawPriv;
344 rrb->base.InternalFormat = _mesa_get_format_base_format(format);
345
346 rrb->base.Delete = radeon_delete_renderbuffer;
347 rrb->base.AllocStorage = radeon_alloc_window_storage;
348 rrb->base.GetPointer = radeon_get_pointer;
349
350 rrb->bo = NULL;
351 return rrb;
352 }
353
354 static struct gl_renderbuffer *
355 radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
356 {
357 struct radeon_renderbuffer *rrb;
358
359 rrb = CALLOC_STRUCT(radeon_renderbuffer);
360
361 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
362 "%s(%p, rrb %p) \n",
363 __func__, ctx, rrb);
364
365 if (!rrb)
366 return NULL;
367
368 _mesa_init_renderbuffer(&rrb->base, name);
369 rrb->base.ClassID = RADEON_RB_CLASS;
370
371 rrb->base.Delete = radeon_delete_renderbuffer;
372 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
373 rrb->base.GetPointer = radeon_get_pointer;
374
375 return &rrb->base;
376 }
377
378 static void
379 radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
380 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
381 {
382 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
383 "%s(%p, fb %p, target %s) \n",
384 __func__, ctx, fb,
385 _mesa_lookup_enum_by_nr(target));
386
387 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
388 radeon_draw_buffer(ctx, fb);
389 }
390 else {
391 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
392 }
393 }
394
395 static void
396 radeon_framebuffer_renderbuffer(GLcontext * ctx,
397 struct gl_framebuffer *fb,
398 GLenum attachment, struct gl_renderbuffer *rb)
399 {
400
401 if (ctx->Driver.Flush)
402 ctx->Driver.Flush(ctx); /* +r6/r7 */
403
404 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
405 "%s(%p, fb %p, rb %p) \n",
406 __func__, ctx, fb, rb);
407
408 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
409 radeon_draw_buffer(ctx, fb);
410 }
411
412
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).
418 */
419 static GLboolean
420 radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb,
421 struct gl_texture_image *texImage)
422 {
423 int retry = 0;
424 gl_format texFormat;
425
426 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
427 "%s(%p, rrb %p, texImage %p) \n",
428 __func__, ctx, rrb, texImage);
429
430 restart:
431 if (texImage->TexFormat == _dri_texformat_argb8888) {
432 rrb->base.DataType = GL_UNSIGNED_BYTE;
433 DBG("Render to RGBA8 texture OK\n");
434 }
435 else if (texImage->TexFormat == _dri_texformat_rgb565) {
436 rrb->base.DataType = GL_UNSIGNED_BYTE;
437 DBG("Render to RGB5 texture OK\n");
438 }
439 else if (texImage->TexFormat == _dri_texformat_argb1555) {
440 rrb->base.DataType = GL_UNSIGNED_BYTE;
441 DBG("Render to ARGB1555 texture OK\n");
442 }
443 else if (texImage->TexFormat == _dri_texformat_argb4444) {
444 rrb->base.DataType = GL_UNSIGNED_BYTE;
445 DBG("Render to ARGB4444 texture OK\n");
446 }
447 else if (texImage->TexFormat == MESA_FORMAT_Z16) {
448 rrb->base.DataType = GL_UNSIGNED_SHORT;
449 DBG("Render to DEPTH16 texture OK\n");
450 }
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");
454 }
455 else {
456 /* try redoing the FBO */
457 if (retry == 1) {
458 DBG("Render to texture BAD FORMAT %d\n",
459 texImage->TexFormat);
460 return GL_FALSE;
461 }
462 /* XXX why is the tex format being set here?
463 * I think this can be removed.
464 */
465 texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0,
466 _mesa_get_format_datatype(texImage->TexFormat),
467 1);
468
469 retry++;
470 goto restart;
471 }
472
473 texFormat = texImage->TexFormat;
474
475 rrb->base.Format = texFormat;
476
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);
481
482 rrb->base.Width = texImage->Width;
483 rrb->base.Height = texImage->Height;
484
485 rrb->base.Delete = radeon_delete_renderbuffer;
486 rrb->base.AllocStorage = radeon_nop_alloc_storage;
487
488 return GL_TRUE;
489 }
490
491
492 static struct radeon_renderbuffer *
493 radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
494 {
495 const GLuint name = ~0; /* not significant, but distinct for debugging */
496 struct radeon_renderbuffer *rrb;
497
498 /* make an radeon_renderbuffer to wrap the texture image */
499 rrb = CALLOC_STRUCT(radeon_renderbuffer);
500
501 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
502 "%s(%p, rrb %p, texImage %p) \n",
503 __func__, ctx, rrb, texImage);
504
505 if (!rrb) {
506 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
507 return NULL;
508 }
509
510 _mesa_init_renderbuffer(&rrb->base, name);
511 rrb->base.ClassID = RADEON_RB_CLASS;
512
513 if (!radeon_update_wrapper(ctx, rrb, texImage)) {
514 free(rrb);
515 return NULL;
516 }
517
518 return rrb;
519
520 }
521 static void
522 radeon_render_texture(GLcontext * ctx,
523 struct gl_framebuffer *fb,
524 struct gl_renderbuffer_attachment *att)
525 {
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;
530 GLuint imageOffset;
531
532 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
533 "%s(%p, fb %p, rrb %p, att %p)\n",
534 __func__, ctx, fb, rrb, att);
535
536 (void) fb;
537
538 ASSERT(newImage);
539
540 if (newImage->Border != 0) {
541 /* Fallback on drawing to a texture with a border, which won't have a
542 * miptree.
543 */
544 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
545 _mesa_render_texture(ctx, fb, att);
546 return;
547 }
548 else if (!rrb) {
549 rrb = radeon_wrap_texture(ctx, newImage);
550 if (rrb) {
551 /* bind the wrapper to the attachment point */
552 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
553 }
554 else {
555 /* fallback to software rendering */
556 _mesa_render_texture(ctx, fb, att);
557 return;
558 }
559 }
560
561 if (!radeon_update_wrapper(ctx, rrb, newImage)) {
562 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
563 _mesa_render_texture(ctx, fb, att);
564 return;
565 }
566
567 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
568 _glthread_GetID(),
569 att->Texture->Name, newImage->Width, newImage->Height,
570 rrb->base.RefCount);
571
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) {
575 if (rrb->bo)
576 radeon_bo_unref(rrb->bo);
577 rrb->bo = radeon_image->mt->bo;
578 radeon_bo_ref(rrb->bo);
579 }
580
581 /* compute offset of the particular 2D image within the texture region */
582 imageOffset = radeon_miptree_image_offset(radeon_image->mt,
583 att->CubeMapFace,
584 att->TextureLevel);
585
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 *
589 att->Zoffset;
590 }
591
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;
596
597 /* update drawing region, etc */
598 radeon_draw_buffer(ctx, fb);
599 }
600
601 static void
602 radeon_finish_render_texture(GLcontext * ctx,
603 struct gl_renderbuffer_attachment *att)
604 {
605
606 }
607 static void
608 radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
609 {
610 }
611
612 void radeon_fbo_init(struct radeon_context *radeon)
613 {
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;
623 }
624
625
626 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
627 struct radeon_bo *bo)
628 {
629 struct radeon_bo *old;
630 old = rb->bo;
631 rb->bo = bo;
632 radeon_bo_ref(bo);
633 if (old)
634 radeon_bo_unref(old);
635 }