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
49static void
50radeon_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
51{
52  struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
53
54  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
55		"%s(rb %p, rrb %p) \n",
56		__func__, rb, rrb);
57
58  assert(rrb);
59
60  if (rrb && rrb->bo) {
61    radeon_bo_unref(rrb->bo);
62  }
63  _mesa_delete_renderbuffer(ctx, rb);
64}
65
66#if defined(RADEON_R100)
67static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb,
68			       GLint x, GLint y)
69{
70    GLuint ba, address = 0;
71
72    ba = (y >> 4) * (rrb->pitch >> 6) + (x >> 4);
73
74    address |= (x & 0x7) << 2;
75    address |= (y & 0x3) << 5;
76    address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5;
77    address |= (ba & 3) << 8;
78    address |= (y & 0x8) << 7;
79    address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7;
80    address |= (ba & ~0x3) << 10;
81    return address;
82}
83
84static GLuint get_depth_z16(const struct radeon_renderbuffer * rrb,
85			       GLint x, GLint y)
86{
87    GLuint ba, address = 0;                   /* a[0]    = 0           */
88
89    ba = (y / 16) * (rrb->pitch >> 6) + (x / 32);
90
91    address |= (x & 0x7) << 1;                /* a[1..3] = x[0..2]     */
92    address |= (y & 0x7) << 4;                /* a[4..6] = y[0..2]     */
93    address |= (x & 0x8) << 4;                /* a[7]    = x[3]        */
94    address |= (ba & 0x3) << 8;               /* a[8..9] = ba[0..1]    */
95    address |= (y & 0x8) << 7;                /* a[10]   = y[3]        */
96    address |= ((x & 0x10) ^ (y & 0x10)) << 7;/* a[11]   = x[4] ^ y[4] */
97    address |= (ba & ~0x3) << 10;             /* a[12..] = ba[2..] */
98    return address;
99}
100#endif
101
102#if defined(RADEON_R200)
103static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb,
104				 GLint x, GLint y)
105{
106    GLuint offset;
107    GLuint b;
108    offset = 0;
109    b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5));
110    offset += (b >> 1) << 12;
111    offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
112    offset += ((y >> 2) & 0x3) << 9;
113    offset += ((x >> 2) & 0x1) << 8;
114    offset += ((x >> 3) & 0x3) << 6;
115    offset += ((y >> 1) & 0x1) << 5;
116    offset += ((x >> 1) & 0x1) << 4;
117    offset += (y & 0x1) << 3;
118    offset += (x & 0x1) << 2;
119
120    return offset;
121}
122
123static GLuint get_depth_z16(const struct radeon_renderbuffer *rrb,
124			       GLint x, GLint y)
125{
126   GLuint offset;
127   GLuint b;
128
129   offset = 0;
130   b = (((y  >> 4) * (rrb->pitch >> 7) + (x >> 6)));
131   offset += (b >> 1) << 12;
132   offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
133   offset += ((y >> 2) & 0x3) << 9;
134   offset += ((x >> 3) & 0x1) << 8;
135   offset += ((x >> 4) & 0x3) << 6;
136   offset += ((x >> 2) & 0x1) << 5;
137   offset += ((y >> 1) & 0x1) << 4;
138   offset += ((x >> 1) & 0x1) << 3;
139   offset += (y & 0x1) << 2;
140   offset += (x & 0x1) << 1;
141
142   return offset;
143}
144#endif
145
146static void
147radeon_map_renderbuffer_s8z24(struct gl_renderbuffer *rb,
148		       GLuint x, GLuint y, GLuint w, GLuint h,
149		       GLbitfield mode,
150		       GLubyte **out_map,
151		       GLint *out_stride)
152{
153    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
154    uint32_t *untiled_s8z24_map, *tiled_s8z24_map;
155    int ret;
156    int y_flip = (rb->Name == 0) ? -1 : 1;
157    int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
158    uint32_t pitch = w * rrb->cpp;
159
160    rrb->map_pitch = pitch;
161
162    rrb->map_buffer = malloc(w * h * 4);
163    ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
164    assert(!ret);
165    (void) ret;
166    untiled_s8z24_map = rrb->map_buffer;
167    tiled_s8z24_map = rrb->bo->ptr;
168
169    for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) {
170	for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
171	    uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
172	    uint32_t src_offset = get_depth_z32(rrb, x + pix_x, flipped_y);
173	    uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
174	    untiled_s8z24_map[dst_offset/4] = tiled_s8z24_map[src_offset/4];
175	}
176    }
177
178    radeon_bo_unmap(rrb->bo);
179
180    *out_map = rrb->map_buffer;
181    *out_stride = rrb->map_pitch;
182}
183
184static void
185radeon_map_renderbuffer_z16(struct gl_renderbuffer *rb,
186			    GLuint x, GLuint y, GLuint w, GLuint h,
187			    GLbitfield mode,
188			    GLubyte **out_map,
189			    GLint *out_stride)
190{
191    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
192    uint16_t *untiled_z16_map, *tiled_z16_map;
193    int ret;
194    int y_flip = (rb->Name == 0) ? -1 : 1;
195    int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
196    uint32_t pitch = w * rrb->cpp;
197
198    rrb->map_pitch = pitch;
199
200    rrb->map_buffer = malloc(w * h * 2);
201    ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
202    assert(!ret);
203    (void) ret;
204
205    untiled_z16_map = rrb->map_buffer;
206    tiled_z16_map = rrb->bo->ptr;
207
208    for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) {
209	for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
210	    uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
211	    uint32_t src_offset = get_depth_z16(rrb, x + pix_x, flipped_y);
212	    uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
213	    untiled_z16_map[dst_offset/2] = tiled_z16_map[src_offset/2];
214	}
215    }
216
217    radeon_bo_unmap(rrb->bo);
218
219    *out_map = rrb->map_buffer;
220    *out_stride = rrb->map_pitch;
221}
222
223static void
224radeon_map_renderbuffer(struct gl_context *ctx,
225		       struct gl_renderbuffer *rb,
226		       GLuint x, GLuint y, GLuint w, GLuint h,
227		       GLbitfield mode,
228		       GLubyte **out_map,
229		       GLint *out_stride,
230		       bool flip_y)
231{
232   struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
233   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
234   GLubyte *map;
235   GLboolean ok;
236   int stride, flip_stride;
237   int ret;
238   int src_x, src_y;
239
240   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
241   assert((rb->Name == 0) == flip_y);
242
243   if (!rrb || !rrb->bo) {
244	   *out_map = NULL;
245	   *out_stride = 0;
246	   return;
247   }
248
249   rrb->map_mode = mode;
250   rrb->map_x = x;
251   rrb->map_y = y;
252   rrb->map_w = w;
253   rrb->map_h = h;
254   rrb->map_pitch = rrb->pitch;
255
256   ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
257   if (ok) {
258       if (rb->Name) {
259	   src_x = x;
260	   src_y = y;
261       } else {
262	   src_x = x;
263	   src_y = rrb->base.Base.Height - y - h;
264       }
265
266       /* Make a temporary buffer and blit the current contents of the renderbuffer
267	* out to it.  This gives us linear access to the buffer, instead of having
268	* to do detiling in software.
269	*/
270
271       rrb->map_pitch = rrb->pitch;
272
273       assert(!rrb->map_bo);
274       rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
275				    rrb->map_pitch * h, 4,
276				    RADEON_GEM_DOMAIN_GTT, 0);
277
278       ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
279			     rb->Format, rrb->pitch / rrb->cpp,
280			     rb->Width, rb->Height,
281			     src_x, src_y,
282			     rrb->map_bo, 0,
283			     rb->Format, rrb->map_pitch / rrb->cpp,
284			     w, h,
285			     0, 0,
286			     w, h,
287			     GL_FALSE);
288       assert(ok);
289
290       ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
291       assert(!ret);
292
293       map = rrb->map_bo->ptr;
294
295       if (rb->Name) {
296	   *out_map = map;
297	   *out_stride = rrb->map_pitch;
298       } else {
299	   *out_map = map + (h - 1) * rrb->map_pitch;
300	   *out_stride = -rrb->map_pitch;
301       }
302       return;
303   }
304
305   /* sw fallback flush stuff */
306   if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
307      radeon_firevertices(rmesa);
308   }
309
310   if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
311       if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
312	   radeon_map_renderbuffer_s8z24(rb, x, y, w, h,
313					 mode, out_map, out_stride);
314	   return;
315       }
316       if (rb->Format == MESA_FORMAT_Z_UNORM16) {
317	   radeon_map_renderbuffer_z16(rb, x, y, w, h,
318				       mode, out_map, out_stride);
319	   return;
320       }
321   }
322
323   ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
324   assert(!ret);
325   (void) ret;
326
327   map = rrb->bo->ptr;
328   stride = rrb->map_pitch;
329
330   if (rb->Name == 0) {
331      y = rb->Height - 1 - y;
332      flip_stride = -stride;
333   } else {
334      flip_stride = stride;
335      map += rrb->draw_offset;
336   }
337
338   map += x * rrb->cpp;
339   map += (int)y * stride;
340
341   *out_map = map;
342   *out_stride = flip_stride;
343}
344
345static void
346radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx,
347			  struct gl_renderbuffer *rb)
348{
349   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
350
351   if (!rrb->map_buffer)
352     return;
353
354   if (rrb->map_mode & GL_MAP_WRITE_BIT) {
355       uint32_t *untiled_s8z24_map = rrb->map_buffer;
356       uint32_t *tiled_s8z24_map;
357       int y_flip = (rb->Name == 0) ? -1 : 1;
358       int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
359
360       radeon_bo_map(rrb->bo, 1);
361
362       tiled_s8z24_map = rrb->bo->ptr;
363
364       for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
365	   for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
366	       uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
367	       uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y);
368	       uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
369	       tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4];
370	   }
371       }
372       radeon_bo_unmap(rrb->bo);
373   }
374   free(rrb->map_buffer);
375   rrb->map_buffer = NULL;
376}
377
378static void
379radeon_unmap_renderbuffer_z16(struct gl_context *ctx,
380			      struct gl_renderbuffer *rb)
381{
382   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
383
384   if (!rrb->map_buffer)
385     return;
386
387   if (rrb->map_mode & GL_MAP_WRITE_BIT) {
388       uint16_t *untiled_z16_map = rrb->map_buffer;
389       uint16_t *tiled_z16_map;
390       int y_flip = (rb->Name == 0) ? -1 : 1;
391       int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
392
393       radeon_bo_map(rrb->bo, 1);
394
395       tiled_z16_map = rrb->bo->ptr;
396
397       for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
398	   for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
399	       uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
400	       uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y);
401	       uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
402	       tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2];
403	   }
404       }
405       radeon_bo_unmap(rrb->bo);
406   }
407   free(rrb->map_buffer);
408   rrb->map_buffer = NULL;
409}
410
411
412static void
413radeon_unmap_renderbuffer(struct gl_context *ctx,
414			  struct gl_renderbuffer *rb)
415{
416   struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
417   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
418
419   if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
420       if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
421	   radeon_unmap_renderbuffer_s8z24(ctx, rb);
422	   return;
423       }
424       if (rb->Format == MESA_FORMAT_Z_UNORM16) {
425	   radeon_unmap_renderbuffer_z16(ctx, rb);
426	   return;
427       }
428   }
429
430   if (!rrb->map_bo) {
431	   if (rrb->bo)
432		   radeon_bo_unmap(rrb->bo);
433	   return;
434   }
435
436   radeon_bo_unmap(rrb->map_bo);
437
438   if (rrb->map_mode & GL_MAP_WRITE_BIT) {
439      GLboolean ok;
440      ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
441			    rb->Format, rrb->map_pitch / rrb->cpp,
442			    rrb->map_w, rrb->map_h,
443			    0, 0,
444			    rrb->bo, rrb->draw_offset,
445			    rb->Format, rrb->pitch / rrb->cpp,
446			    rb->Width, rb->Height,
447			    rrb->map_x, rrb->map_y,
448			    rrb->map_w, rrb->map_h,
449			    GL_FALSE);
450      assert(ok);
451      (void) 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 */
463static GLboolean
464radeon_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_Z24_UNORM_S8_UINT;
511      cpp = 4;
512      break;
513   case GL_DEPTH_COMPONENT16:
514      rb->Format = MESA_FORMAT_Z_UNORM16;
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_Z24_UNORM_X8_UINT;
521      cpp = 4;
522      break;
523   case GL_DEPTH_STENCIL_EXT:
524   case GL_DEPTH24_STENCIL8_EXT:
525      rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT;
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
562static void
563radeon_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   rb->NeedsFinishRenderTexture = GL_TRUE;
601}
602
603/**
604 * Called for each hardware renderbuffer when a _window_ is resized.
605 * Just update fields.
606 * Not used for user-created renderbuffers!
607 */
608static GLboolean
609radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
610                           GLenum internalFormat, GLuint width, GLuint height)
611{
612   assert(rb->Name == 0);
613   rb->Width = width;
614   rb->Height = height;
615   rb->InternalFormat = internalFormat;
616  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
617		"%s(%p, rb %p) \n",
618		__func__, ctx, rb);
619
620
621   return GL_TRUE;
622}
623
624/** Dummy function for gl_renderbuffer::AllocStorage() */
625static GLboolean
626radeon_nop_alloc_storage(struct gl_context * ctx,
627			 UNUSED struct gl_renderbuffer *rb,
628			 UNUSED GLenum internalFormat,
629			 UNUSED GLuint width,
630			 UNUSED GLuint height)
631{
632   _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
633   return GL_FALSE;
634}
635
636
637/**
638 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
639 * Not used for user-created renderbuffers.
640 */
641struct radeon_renderbuffer *
642radeon_create_renderbuffer(mesa_format format, __DRIdrawable *driDrawPriv)
643{
644    struct radeon_renderbuffer *rrb;
645    struct gl_renderbuffer *rb;
646
647    rrb = CALLOC_STRUCT(radeon_renderbuffer);
648
649    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
650		"%s( rrb %p ) \n",
651		__func__, rrb);
652
653    if (!rrb)
654	return NULL;
655
656    rb = &rrb->base.Base;
657
658    _mesa_init_renderbuffer(rb, 0);
659    rb->ClassID = RADEON_RB_CLASS;
660    rb->Format = format;
661    rb->_BaseFormat = _mesa_get_format_base_format(format);
662    rb->InternalFormat = _mesa_get_format_base_format(format);
663
664    rrb->dPriv = driDrawPriv;
665
666    rb->Delete = radeon_delete_renderbuffer;
667    rb->AllocStorage = radeon_alloc_window_storage;
668
669    rrb->bo = NULL;
670    return rrb;
671}
672
673static struct gl_renderbuffer *
674radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
675{
676  struct radeon_renderbuffer *rrb;
677  struct gl_renderbuffer *rb;
678
679
680  rrb = CALLOC_STRUCT(radeon_renderbuffer);
681
682  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
683		"%s(%p, rrb %p) \n",
684		__func__, ctx, rrb);
685
686  if (!rrb)
687    return NULL;
688
689  rb = &rrb->base.Base;
690
691  _mesa_init_renderbuffer(rb, name);
692  rb->ClassID = RADEON_RB_CLASS;
693  rb->Delete = radeon_delete_renderbuffer;
694  rb->AllocStorage = radeon_alloc_renderbuffer_storage;
695
696  return rb;
697}
698
699static void
700radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
701                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
702{
703  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
704		"%s(%p, fb %p, target %s) \n",
705		__func__, ctx, fb,
706		_mesa_enum_to_string(target));
707
708   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
709      radeon_draw_buffer(ctx, fb);
710   }
711   else {
712      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
713   }
714}
715
716static void
717radeon_framebuffer_renderbuffer(struct gl_context * ctx,
718                               struct gl_framebuffer *fb,
719                               GLenum attachment, struct gl_renderbuffer *rb)
720{
721
722	if (ctx->Driver.Flush)
723		ctx->Driver.Flush(ctx); /* +r6/r7 */
724
725	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
726		"%s(%p, fb %p, rb %p) \n",
727		__func__, ctx, fb, rb);
728
729   _mesa_FramebufferRenderbuffer_sw(ctx, fb, attachment, rb);
730   radeon_draw_buffer(ctx, fb);
731}
732
733static GLboolean
734radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
735		     struct gl_texture_image *texImage)
736{
737	struct gl_renderbuffer *rb = &rrb->base.Base;
738
739	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
740		"%s(%p, rrb %p, texImage %p, texFormat %s) \n",
741		__func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
742
743	rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
744	rrb->pitch = texImage->Width * rrb->cpp;
745	rb->Format = texImage->TexFormat;
746	rb->InternalFormat = texImage->InternalFormat;
747	rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
748	rb->Width = texImage->Width;
749	rb->Height = texImage->Height;
750	rb->Delete = radeon_delete_renderbuffer;
751	rb->AllocStorage = radeon_nop_alloc_storage;
752
753	return GL_TRUE;
754}
755
756static void
757radeon_render_texture(struct gl_context * ctx,
758                     struct gl_framebuffer *fb,
759                     struct gl_renderbuffer_attachment *att)
760{
761   struct gl_renderbuffer *rb = att->Renderbuffer;
762   struct gl_texture_image *newImage = rb->TexImage;
763   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
764   radeon_texture_image *radeon_image;
765   GLuint imageOffset;
766
767  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
768		"%s(%p, fb %p, rrb %p, att %p)\n",
769		__func__, ctx, fb, rrb, att);
770
771   (void) fb;
772
773   assert(newImage);
774
775   radeon_image = (radeon_texture_image *)newImage;
776
777   if (!radeon_image->mt) {
778      /* Fallback on drawing to a texture without a miptree.
779       */
780      _swrast_render_texture(ctx, fb, att);
781      return;
782   }
783
784   if (!radeon_update_wrapper(ctx, rrb, newImage)) {
785       _swrast_render_texture(ctx, fb, att);
786       return;
787   }
788
789   DBG("Begin render texture tex=%u w=%d h=%d refcount=%d\n",
790       att->Texture->Name, newImage->Width, newImage->Height,
791       rb->RefCount);
792
793   /* point the renderbufer's region to the texture image region */
794   if (rrb->bo != radeon_image->mt->bo) {
795      if (rrb->bo)
796  	radeon_bo_unref(rrb->bo);
797      rrb->bo = radeon_image->mt->bo;
798      radeon_bo_ref(rrb->bo);
799   }
800
801   /* compute offset of the particular 2D image within the texture region */
802   imageOffset = radeon_miptree_image_offset(radeon_image->mt,
803                                            att->CubeMapFace,
804                                            att->TextureLevel);
805
806   if (att->Texture->Target == GL_TEXTURE_3D) {
807      imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
808                     radeon_image->mt->levels[att->TextureLevel].height *
809                     att->Zoffset;
810   }
811
812   /* store that offset in the region, along with the correct pitch for
813    * the image we are rendering to */
814   rrb->draw_offset = imageOffset;
815   rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
816   radeon_image->used_as_render_target = GL_TRUE;
817
818   /* update drawing region, etc */
819   radeon_draw_buffer(ctx, fb);
820}
821
822static void
823radeon_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
824{
825    struct gl_texture_image *image = rb->TexImage;
826    radeon_texture_image *radeon_image = (radeon_texture_image *)image;
827
828    if (radeon_image)
829	radeon_image->used_as_render_target = GL_FALSE;
830
831    if (ctx->Driver.Flush)
832        ctx->Driver.Flush(ctx); /* +r6/r7 */
833}
834static void
835radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
836{
837	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
838	mesa_format mesa_format;
839	int i;
840
841	for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
842		struct gl_renderbuffer_attachment *att;
843		if (i == -2) {
844			att = &fb->Attachment[BUFFER_DEPTH];
845		} else if (i == -1) {
846			att = &fb->Attachment[BUFFER_STENCIL];
847		} else {
848			att = &fb->Attachment[BUFFER_COLOR0 + i];
849		}
850
851		if (att->Type == GL_TEXTURE) {
852			mesa_format = att->Renderbuffer->TexImage->TexFormat;
853		} else {
854			/* All renderbuffer formats are renderable, but not sampable */
855			continue;
856		}
857
858		if (!radeon->vtbl.is_format_renderable(mesa_format)){
859			fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
860			radeon_print(RADEON_TEXTURE, RADEON_TRACE,
861						"%s: HW doesn't support format %s as output format of attachment %d\n",
862						__func__, _mesa_get_format_name(mesa_format), i);
863			return;
864		}
865	}
866}
867
868void radeon_fbo_init(struct radeon_context *radeon)
869{
870  radeon->glCtx.Driver.NewRenderbuffer = radeon_new_renderbuffer;
871  radeon->glCtx.Driver.MapRenderbuffer = radeon_map_renderbuffer;
872  radeon->glCtx.Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
873  radeon->glCtx.Driver.BindFramebuffer = radeon_bind_framebuffer;
874  radeon->glCtx.Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
875  radeon->glCtx.Driver.RenderTexture = radeon_render_texture;
876  radeon->glCtx.Driver.FinishRenderTexture = radeon_finish_render_texture;
877  radeon->glCtx.Driver.ValidateFramebuffer = radeon_validate_framebuffer;
878  radeon->glCtx.Driver.BlitFramebuffer = _mesa_meta_and_swrast_BlitFramebuffer;
879  radeon->glCtx.Driver.EGLImageTargetRenderbufferStorage =
880	  radeon_image_target_renderbuffer_storage;
881}
882
883
884void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
885				struct radeon_bo *bo)
886{
887  struct radeon_bo *old;
888  old = rb->bo;
889  rb->bo = bo;
890  radeon_bo_ref(bo);
891  if (old)
892    radeon_bo_unref(old);
893}
894