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