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