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