radeon: texture/renderbuffer overhaul.
[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/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"
40
41 #include "radeon_common.h"
42 #include "radeon_mipmap_tree.h"
43
44 #define FILE_DEBUG_FLAG RADEON_TEXTURE
45 #define DBG(...) do { \
46 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
47 printf(__VA_ARGS__); \
48 } while(0)
49
50 static struct gl_framebuffer *
51 radeon_new_framebuffer(struct gl_context *ctx, GLuint name)
52 {
53 return _mesa_new_framebuffer(ctx, name);
54 }
55
56 static void
57 radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
58 {
59 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
60
61 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
62 "%s(rb %p, rrb %p) \n",
63 __func__, rb, rrb);
64
65 ASSERT(rrb);
66
67 if (rrb && rrb->bo) {
68 radeon_bo_unref(rrb->bo);
69 }
70 free(rrb);
71 }
72
73 static void
74 radeon_map_renderbuffer(struct gl_context *ctx,
75 struct gl_renderbuffer *rb,
76 GLuint x, GLuint y, GLuint w, GLuint h,
77 GLbitfield mode,
78 GLubyte **out_map,
79 GLint *out_stride)
80 {
81 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
82 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
83 GLubyte *map;
84 GLboolean ok;
85 int stride, flip_stride;
86 int ret;
87 int src_x, src_y;
88
89 if (!rrb || !rrb->bo) {
90 *out_map = NULL;
91 *out_stride = 0;
92 return;
93 }
94
95 rrb->map_mode = mode;
96 rrb->map_x = x;
97 rrb->map_y = y;
98 rrb->map_w = w;
99 rrb->map_h = h;
100 rrb->map_pitch = rrb->pitch;
101
102 ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
103 if (ok) {
104 if (rb->Name) {
105 src_x = x;
106 src_y = y;
107 } else {
108 src_x = x;
109 src_y = rrb->base.Height - y - h;
110 }
111
112 /* Make a temporary buffer and blit the current contents of the renderbuffer
113 * out to it. This gives us linear access to the buffer, instead of having
114 * to do detiling in software.
115 */
116
117 rrb->map_pitch = rrb->pitch;
118
119 assert(!rrb->map_bo);
120 rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
121 rrb->map_pitch * h, 4,
122 RADEON_GEM_DOMAIN_GTT, 0);
123
124 ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
125 rb->Format, rrb->pitch / rrb->cpp,
126 rb->Width, rb->Height,
127 src_x, src_y,
128 rrb->map_bo, 0,
129 rb->Format, rrb->map_pitch / rrb->cpp,
130 w, h,
131 0, 0,
132 w, h,
133 GL_FALSE);
134 assert(ok);
135
136 ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
137 assert(!ret);
138
139 map = rrb->map_bo->ptr;
140
141 if (rb->Name) {
142 *out_map = map;
143 *out_stride = rrb->map_pitch;
144 } else {
145 *out_map = map + (h - 1) * rrb->map_pitch;
146 *out_stride = -rrb->map_pitch;
147 }
148 return;
149 }
150
151 /* sw fallback flush stuff */
152 if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
153 radeon_firevertices(rmesa);
154 }
155
156 ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
157 assert(!ret);
158
159 map = rrb->bo->ptr;
160 stride = rrb->map_pitch;
161
162 if (rb->Name == 0) {
163 y = rb->Height - 1 - y;
164 flip_stride = -stride;
165 } else {
166 flip_stride = stride;
167 map += rrb->draw_offset;
168 }
169
170 map += x * rrb->cpp;
171 map += (int)y * stride;
172
173 *out_map = map;
174 *out_stride = flip_stride;
175 }
176
177 static void
178 radeon_unmap_renderbuffer(struct gl_context *ctx,
179 struct gl_renderbuffer *rb)
180 {
181 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
182 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
183 GLboolean ok;
184
185 if (!rrb->map_bo) {
186 if (rrb->bo)
187 radeon_bo_unmap(rrb->bo);
188 return;
189 }
190
191 radeon_bo_unmap(rrb->map_bo);
192
193 if (rrb->map_mode & GL_MAP_WRITE_BIT) {
194 ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
195 rb->Format, rrb->map_pitch / rrb->cpp,
196 rrb->map_w, rrb->map_h,
197 0, 0,
198 rrb->bo, rrb->draw_offset,
199 rb->Format, rrb->pitch / rrb->cpp,
200 rb->Width, rb->Height,
201 rrb->map_x, rrb->map_y,
202 rrb->map_w, rrb->map_h,
203 GL_FALSE);
204 assert(ok);
205 }
206
207 radeon_bo_unref(rrb->map_bo);
208 rrb->map_bo = NULL;
209 }
210
211 static void *
212 radeon_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb,
213 GLint x, GLint y)
214 {
215 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
216 "%s(%p, rb %p) \n",
217 __func__, ctx, rb);
218
219 return NULL;
220 }
221
222 /**
223 * Called via glRenderbufferStorageEXT() to set the format and allocate
224 * storage for a user-created renderbuffer.
225 */
226 static GLboolean
227 radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
228 GLenum internalFormat,
229 GLuint width, GLuint height)
230 {
231 struct radeon_context *radeon = RADEON_CONTEXT(ctx);
232 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
233 uint32_t size, pitch;
234 int cpp;
235
236 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
237 "%s(%p, rb %p) \n",
238 __func__, ctx, rb);
239
240 ASSERT(rb->Name != 0);
241 switch (internalFormat) {
242 case GL_R3_G3_B2:
243 case GL_RGB4:
244 case GL_RGB5:
245 rb->Format = _radeon_texformat_rgb565;
246 rb->DataType = GL_UNSIGNED_BYTE;
247 cpp = 2;
248 break;
249 case GL_RGB:
250 case GL_RGB8:
251 case GL_RGB10:
252 case GL_RGB12:
253 case GL_RGB16:
254 rb->Format = _radeon_texformat_argb8888;
255 rb->DataType = GL_UNSIGNED_BYTE;
256 cpp = 4;
257 break;
258 case GL_RGBA:
259 case GL_RGBA2:
260 case GL_RGBA4:
261 case GL_RGB5_A1:
262 case GL_RGBA8:
263 case GL_RGB10_A2:
264 case GL_RGBA12:
265 case GL_RGBA16:
266 rb->Format = _radeon_texformat_argb8888;
267 rb->DataType = GL_UNSIGNED_BYTE;
268 cpp = 4;
269 break;
270 case GL_STENCIL_INDEX:
271 case GL_STENCIL_INDEX1_EXT:
272 case GL_STENCIL_INDEX4_EXT:
273 case GL_STENCIL_INDEX8_EXT:
274 case GL_STENCIL_INDEX16_EXT:
275 /* alloc a depth+stencil buffer */
276 rb->Format = MESA_FORMAT_S8_Z24;
277 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
278 cpp = 4;
279 break;
280 case GL_DEPTH_COMPONENT16:
281 rb->Format = MESA_FORMAT_Z16;
282 rb->DataType = GL_UNSIGNED_SHORT;
283 cpp = 2;
284 break;
285 case GL_DEPTH_COMPONENT:
286 case GL_DEPTH_COMPONENT24:
287 case GL_DEPTH_COMPONENT32:
288 rb->Format = MESA_FORMAT_X8_Z24;
289 rb->DataType = GL_UNSIGNED_INT;
290 cpp = 4;
291 break;
292 case GL_DEPTH_STENCIL_EXT:
293 case GL_DEPTH24_STENCIL8_EXT:
294 rb->Format = MESA_FORMAT_S8_Z24;
295 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
296 cpp = 4;
297 break;
298 default:
299 _mesa_problem(ctx,
300 "Unexpected format in radeon_alloc_renderbuffer_storage");
301 return GL_FALSE;
302 }
303
304 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
305
306 if (ctx->Driver.Flush)
307 ctx->Driver.Flush(ctx); /* +r6/r7 */
308
309 if (rrb->bo)
310 radeon_bo_unref(rrb->bo);
311
312 pitch = ((cpp * width + 63) & ~63) / cpp;
313
314 if (RADEON_DEBUG & RADEON_MEMORY)
315 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
316 height, pitch);
317
318 size = pitch * height * cpp;
319 rrb->pitch = pitch * cpp;
320 rrb->cpp = cpp;
321 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
322 0,
323 size,
324 0,
325 RADEON_GEM_DOMAIN_VRAM,
326 0);
327 rb->Width = width;
328 rb->Height = height;
329 return GL_TRUE;
330 }
331
332 #if FEATURE_OES_EGL_image
333 static void
334 radeon_image_target_renderbuffer_storage(struct gl_context *ctx,
335 struct gl_renderbuffer *rb,
336 void *image_handle)
337 {
338 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
339 struct radeon_renderbuffer *rrb;
340 __DRIscreen *screen;
341 __DRIimage *image;
342
343 screen = radeon->radeonScreen->driScreen;
344 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
345 screen->loaderPrivate);
346 if (image == NULL)
347 return;
348
349 rrb = radeon_renderbuffer(rb);
350
351 if (ctx->Driver.Flush)
352 ctx->Driver.Flush(ctx); /* +r6/r7 */
353
354 if (rrb->bo)
355 radeon_bo_unref(rrb->bo);
356 rrb->bo = image->bo;
357 radeon_bo_ref(rrb->bo);
358 fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle,
359 image->width, image->pitch);
360
361 rrb->cpp = image->cpp;
362 rrb->pitch = image->pitch * image->cpp;
363
364 rb->Format = image->format;
365 rb->InternalFormat = image->internal_format;
366 rb->Width = image->width;
367 rb->Height = image->height;
368 rb->Format = image->format;
369 rb->DataType = image->data_type;
370 rb->_BaseFormat = _mesa_base_fbo_format(radeon->glCtx,
371 image->internal_format);
372 }
373 #endif
374
375 /**
376 * Called for each hardware renderbuffer when a _window_ is resized.
377 * Just update fields.
378 * Not used for user-created renderbuffers!
379 */
380 static GLboolean
381 radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
382 GLenum internalFormat, GLuint width, GLuint height)
383 {
384 ASSERT(rb->Name == 0);
385 rb->Width = width;
386 rb->Height = height;
387 rb->InternalFormat = internalFormat;
388 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
389 "%s(%p, rb %p) \n",
390 __func__, ctx, rb);
391
392
393 return GL_TRUE;
394 }
395
396
397 static void
398 radeon_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
399 GLuint width, GLuint height)
400 {
401 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
402 int i;
403
404 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
405 "%s(%p, fb %p) \n",
406 __func__, ctx, fb);
407
408 _mesa_resize_framebuffer(ctx, fb, width, height);
409
410 fb->Initialized = GL_TRUE; /* XXX remove someday */
411
412 if (fb->Name != 0) {
413 return;
414 }
415
416 /* Make sure all window system renderbuffers are up to date */
417 for (i = 0; i < 2; i++) {
418 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
419
420 /* only resize if size is changing */
421 if (rb && (rb->Width != width || rb->Height != height)) {
422 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
423 }
424 }
425 }
426
427
428 /** Dummy function for gl_renderbuffer::AllocStorage() */
429 static GLboolean
430 radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
431 GLenum internalFormat, GLuint width, GLuint height)
432 {
433 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
434 return GL_FALSE;
435 }
436
437
438 /**
439 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
440 * Not used for user-created renderbuffers.
441 */
442 struct radeon_renderbuffer *
443 radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
444 {
445 struct radeon_renderbuffer *rrb;
446
447 rrb = CALLOC_STRUCT(radeon_renderbuffer);
448
449 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
450 "%s( rrb %p ) \n",
451 __func__, rrb);
452
453 if (!rrb)
454 return NULL;
455
456 _mesa_init_renderbuffer(&rrb->base, 0);
457 rrb->base.ClassID = RADEON_RB_CLASS;
458
459 rrb->base.Format = format;
460
461 switch (format) {
462 case MESA_FORMAT_RGB565:
463 assert(_mesa_little_endian());
464 rrb->base.DataType = GL_UNSIGNED_BYTE;
465 break;
466 case MESA_FORMAT_RGB565_REV:
467 assert(!_mesa_little_endian());
468 rrb->base.DataType = GL_UNSIGNED_BYTE;
469 break;
470 case MESA_FORMAT_XRGB8888:
471 assert(_mesa_little_endian());
472 rrb->base.DataType = GL_UNSIGNED_BYTE;
473 break;
474 case MESA_FORMAT_XRGB8888_REV:
475 assert(!_mesa_little_endian());
476 rrb->base.DataType = GL_UNSIGNED_BYTE;
477 break;
478 case MESA_FORMAT_ARGB8888:
479 assert(_mesa_little_endian());
480 rrb->base.DataType = GL_UNSIGNED_BYTE;
481 break;
482 case MESA_FORMAT_ARGB8888_REV:
483 assert(!_mesa_little_endian());
484 rrb->base.DataType = GL_UNSIGNED_BYTE;
485 break;
486 case MESA_FORMAT_S8:
487 rrb->base.DataType = GL_UNSIGNED_BYTE;
488 break;
489 case MESA_FORMAT_Z16:
490 rrb->base.DataType = GL_UNSIGNED_SHORT;
491 break;
492 case MESA_FORMAT_X8_Z24:
493 rrb->base.DataType = GL_UNSIGNED_INT;
494 break;
495 case MESA_FORMAT_S8_Z24:
496 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
497 break;
498 default:
499 fprintf(stderr, "%s: Unknown format %s\n",
500 __FUNCTION__, _mesa_get_format_name(format));
501 _mesa_delete_renderbuffer(&rrb->base);
502 return NULL;
503 }
504 rrb->base._BaseFormat = _mesa_get_format_base_format(format);
505
506 rrb->dPriv = driDrawPriv;
507 rrb->base.InternalFormat = _mesa_get_format_base_format(format);
508
509 rrb->base.Delete = radeon_delete_renderbuffer;
510 rrb->base.AllocStorage = radeon_alloc_window_storage;
511 rrb->base.GetPointer = radeon_get_pointer;
512
513 rrb->bo = NULL;
514 return rrb;
515 }
516
517 static struct gl_renderbuffer *
518 radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
519 {
520 struct radeon_renderbuffer *rrb;
521
522 rrb = CALLOC_STRUCT(radeon_renderbuffer);
523
524 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
525 "%s(%p, rrb %p) \n",
526 __func__, ctx, rrb);
527
528 if (!rrb)
529 return NULL;
530
531 _mesa_init_renderbuffer(&rrb->base, name);
532 rrb->base.ClassID = RADEON_RB_CLASS;
533
534 rrb->base.Delete = radeon_delete_renderbuffer;
535 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
536 rrb->base.GetPointer = radeon_get_pointer;
537
538 return &rrb->base;
539 }
540
541 static void
542 radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
543 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
544 {
545 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
546 "%s(%p, fb %p, target %s) \n",
547 __func__, ctx, fb,
548 _mesa_lookup_enum_by_nr(target));
549
550 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
551 radeon_draw_buffer(ctx, fb);
552 }
553 else {
554 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
555 }
556 }
557
558 static void
559 radeon_framebuffer_renderbuffer(struct gl_context * ctx,
560 struct gl_framebuffer *fb,
561 GLenum attachment, struct gl_renderbuffer *rb)
562 {
563
564 if (ctx->Driver.Flush)
565 ctx->Driver.Flush(ctx); /* +r6/r7 */
566
567 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
568 "%s(%p, fb %p, rb %p) \n",
569 __func__, ctx, fb, rb);
570
571 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
572 radeon_draw_buffer(ctx, fb);
573 }
574
575 static GLboolean
576 radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
577 struct gl_texture_image *texImage)
578 {
579 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
580 "%s(%p, rrb %p, texImage %p, texFormat %s) \n",
581 __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
582
583 switch (texImage->TexFormat) {
584 case MESA_FORMAT_RGBA8888:
585 case MESA_FORMAT_RGBA8888_REV:
586 case MESA_FORMAT_ARGB8888:
587 case MESA_FORMAT_ARGB8888_REV:
588 case MESA_FORMAT_XRGB8888:
589 case MESA_FORMAT_XRGB8888_REV:
590 case MESA_FORMAT_RGB565:
591 case MESA_FORMAT_RGB565_REV:
592 case MESA_FORMAT_RGBA5551:
593 case MESA_FORMAT_ARGB1555:
594 case MESA_FORMAT_ARGB1555_REV:
595 case MESA_FORMAT_ARGB4444:
596 case MESA_FORMAT_ARGB4444_REV:
597 rrb->base.DataType = GL_UNSIGNED_BYTE;
598 break;
599 case MESA_FORMAT_Z16:
600 rrb->base.DataType = GL_UNSIGNED_SHORT;
601 break;
602 case MESA_FORMAT_X8_Z24:
603 rrb->base.DataType = GL_UNSIGNED_INT;
604 break;
605 case MESA_FORMAT_S8_Z24:
606 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
607 break;
608 default:
609 _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()");
610 }
611
612 rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
613 rrb->pitch = texImage->Width * rrb->cpp;
614 rrb->base.Format = texImage->TexFormat;
615 rrb->base.InternalFormat = texImage->InternalFormat;
616 rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat);
617 rrb->base.Width = texImage->Width;
618 rrb->base.Height = texImage->Height;
619 rrb->base.Delete = radeon_delete_renderbuffer;
620 rrb->base.AllocStorage = radeon_nop_alloc_storage;
621
622 return GL_TRUE;
623 }
624
625
626 static struct radeon_renderbuffer *
627 radeon_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
628 {
629 const GLuint name = ~0; /* not significant, but distinct for debugging */
630 struct radeon_renderbuffer *rrb;
631
632 /* make an radeon_renderbuffer to wrap the texture image */
633 rrb = CALLOC_STRUCT(radeon_renderbuffer);
634
635 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
636 "%s(%p, rrb %p, texImage %p) \n",
637 __func__, ctx, rrb, texImage);
638
639 if (!rrb) {
640 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
641 return NULL;
642 }
643
644 _mesa_init_renderbuffer(&rrb->base, name);
645 rrb->base.ClassID = RADEON_RB_CLASS;
646
647 if (!radeon_update_wrapper(ctx, rrb, texImage)) {
648 free(rrb);
649 return NULL;
650 }
651
652 return rrb;
653
654 }
655 static void
656 radeon_render_texture(struct gl_context * ctx,
657 struct gl_framebuffer *fb,
658 struct gl_renderbuffer_attachment *att)
659 {
660 struct gl_texture_image *newImage
661 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
662 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
663 radeon_texture_image *radeon_image;
664 GLuint imageOffset;
665
666 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
667 "%s(%p, fb %p, rrb %p, att %p)\n",
668 __func__, ctx, fb, rrb, att);
669
670 (void) fb;
671
672 ASSERT(newImage);
673
674 radeon_image = (radeon_texture_image *)newImage;
675
676 if (!radeon_image->mt) {
677 /* Fallback on drawing to a texture without a miptree.
678 */
679 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
680 _swrast_render_texture(ctx, fb, att);
681 return;
682 }
683 else if (!rrb) {
684 rrb = radeon_wrap_texture(ctx, newImage);
685 if (rrb) {
686 /* bind the wrapper to the attachment point */
687 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
688 }
689 else {
690 /* fallback to software rendering */
691 _swrast_render_texture(ctx, fb, att);
692 return;
693 }
694 }
695
696 if (!radeon_update_wrapper(ctx, rrb, newImage)) {
697 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
698 _swrast_render_texture(ctx, fb, att);
699 return;
700 }
701
702 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
703 _glthread_GetID(),
704 att->Texture->Name, newImage->Width, newImage->Height,
705 rrb->base.RefCount);
706
707 /* point the renderbufer's region to the texture image region */
708 if (rrb->bo != radeon_image->mt->bo) {
709 if (rrb->bo)
710 radeon_bo_unref(rrb->bo);
711 rrb->bo = radeon_image->mt->bo;
712 radeon_bo_ref(rrb->bo);
713 }
714
715 /* compute offset of the particular 2D image within the texture region */
716 imageOffset = radeon_miptree_image_offset(radeon_image->mt,
717 att->CubeMapFace,
718 att->TextureLevel);
719
720 if (att->Texture->Target == GL_TEXTURE_3D) {
721 imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
722 radeon_image->mt->levels[att->TextureLevel].height *
723 att->Zoffset;
724 }
725
726 /* store that offset in the region, along with the correct pitch for
727 * the image we are rendering to */
728 rrb->draw_offset = imageOffset;
729 rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
730 radeon_image->used_as_render_target = GL_TRUE;
731
732 /* update drawing region, etc */
733 radeon_draw_buffer(ctx, fb);
734 }
735
736 static void
737 radeon_finish_render_texture(struct gl_context * ctx,
738 struct gl_renderbuffer_attachment *att)
739 {
740 struct gl_texture_object *tex_obj = att->Texture;
741 struct gl_texture_image *image =
742 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
743 radeon_texture_image *radeon_image = (radeon_texture_image *)image;
744
745 if (radeon_image)
746 radeon_image->used_as_render_target = GL_FALSE;
747
748 if (ctx->Driver.Flush)
749 ctx->Driver.Flush(ctx); /* +r6/r7 */
750 }
751 static void
752 radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
753 {
754 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
755 gl_format mesa_format;
756 int i;
757
758 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
759 struct gl_renderbuffer_attachment *att;
760 if (i == -2) {
761 att = &fb->Attachment[BUFFER_DEPTH];
762 } else if (i == -1) {
763 att = &fb->Attachment[BUFFER_STENCIL];
764 } else {
765 att = &fb->Attachment[BUFFER_COLOR0 + i];
766 }
767
768 if (att->Type == GL_TEXTURE) {
769 mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat;
770 } else {
771 /* All renderbuffer formats are renderable, but not sampable */
772 continue;
773 }
774
775 if (!radeon->vtbl.is_format_renderable(mesa_format)){
776 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
777 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
778 "%s: HW doesn't support format %s as output format of attachment %d\n",
779 __FUNCTION__, _mesa_get_format_name(mesa_format), i);
780 return;
781 }
782 }
783 }
784
785 void radeon_fbo_init(struct radeon_context *radeon)
786 {
787 #if FEATURE_EXT_framebuffer_object
788 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
789 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
790 radeon->glCtx->Driver.MapRenderbuffer = radeon_map_renderbuffer;
791 radeon->glCtx->Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
792 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
793 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
794 radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
795 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
796 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
797 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
798 #endif
799 #if FEATURE_EXT_framebuffer_blit
800 radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
801 #endif
802 #if FEATURE_OES_EGL_image
803 radeon->glCtx->Driver.EGLImageTargetRenderbufferStorage =
804 radeon_image_target_renderbuffer_storage;
805 #endif
806 }
807
808
809 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
810 struct radeon_bo *bo)
811 {
812 struct radeon_bo *old;
813 old = rb->bo;
814 rb->bo = bo;
815 radeon_bo_ref(bo);
816 if (old)
817 radeon_bo_unref(old);
818 }