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