radeon_fbo.c revision dca04373c2efb177dbb7dca3ad2b57cb36b2ebe6
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
50static struct gl_framebuffer *
51radeon_new_framebuffer(struct gl_context *ctx, GLuint name)
52{
53  return _mesa_new_framebuffer(ctx, name);
54}
55
56static void
57radeon_delete_renderbuffer(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(rb);
71}
72
73#if defined(RADEON_R100)
74static 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
91static 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)
110static 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
130static 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
153static void
154radeon_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
191static void
192radeon_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
230static void
231radeon_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
347static void
348radeon_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
380static void
381radeon_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
414static void
415radeon_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 */
464static GLboolean
465radeon_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
564static void
565radeon_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 */
610static GLboolean
611radeon_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
627static void
628radeon_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() */
659static GLboolean
660radeon_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 */
672struct radeon_renderbuffer *
673radeon_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
704static struct gl_renderbuffer *
705radeon_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
730static void
731radeon_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
747static void
748radeon_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
764static GLboolean
765radeon_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
788static struct radeon_renderbuffer *
789radeon_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}
817static void
818radeon_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
898static void
899radeon_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}
913static void
914radeon_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
947void 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
971void 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