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