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