Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_fbo.c
index 649f88a061cfe733a3f6a6ec3565cad692812a31..d83b166742c781014cc842b756c9f13f6b103d83 100644 (file)
 #include "main/context.h"
 #include "main/texformat.h"
 #include "main/texrender.h"
+#include "drivers/common/meta.h"
 
 #include "radeon_common.h"
+#include "radeon_mipmap_tree.h"
 
-#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+#define FILE_DEBUG_FLAG RADEON_TEXTURE
 #define DBG(...) do {                                           \
         if (RADEON_DEBUG & FILE_DEBUG_FLAG)                      \
                 _mesa_printf(__VA_ARGS__);                      \
@@ -53,7 +55,6 @@ radeon_new_framebuffer(GLcontext *ctx, GLuint name)
 static void
 radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
 {
-  GET_CURRENT_CONTEXT(ctx);
   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
 
   ASSERT(rrb);
@@ -61,8 +62,6 @@ radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
   if (rrb && rrb->bo) {
     radeon_bo_unref(rrb->bo);
   }
-
-
   _mesa_free(rrb);
 }
 
@@ -148,8 +147,8 @@ radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32:
-      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
-      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+      rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+      rb->DataType = GL_UNSIGNED_INT;
       rb->DepthBits = 24;
       cpp = 4;
       break;
@@ -167,7 +166,8 @@ radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
       return GL_FALSE;
    }
 
-  radeonFlush(ctx);
+  if (ctx->Driver.Flush)
+         ctx->Driver.Flush(ctx); /* +r6/r7 */
 
   if (rrb->bo)
     radeon_bo_unref(rrb->bo);
@@ -178,9 +178,21 @@ radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                                              width, height);
    }
    else {
-     /* TODO Alloc a BO */
-
-     //     rrb->bo = radeon_bo_open();
+     uint32_t size;
+     uint32_t pitch = ((cpp * width + 63) & ~63) / cpp;
+
+     fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
+         height, pitch);
+
+     size = pitch * height * cpp;
+     rrb->pitch = pitch * cpp;
+     rrb->cpp = cpp;
+     rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+                             0,
+                             size,
+                             0,
+                             RADEON_GEM_DOMAIN_VRAM,
+                             0);
      rb->Width = width;
      rb->Height = height;
        return GL_TRUE;
@@ -243,7 +255,7 @@ radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
    return GL_FALSE;
 }
 
-struct gl_renderbuffer *
+struct radeon_renderbuffer *
 radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
 {
     struct radeon_renderbuffer *rrb;
@@ -265,6 +277,15 @@ radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
            rrb->base.BlueBits = 5;
            rrb->base.DataType = GL_UNSIGNED_BYTE;
            break;
+       case GL_RGB8:
+           rrb->base._ActualFormat = GL_RGB8;
+           rrb->base._BaseFormat = GL_RGB;
+           rrb->base.RedBits = 8;
+           rrb->base.GreenBits = 8;
+           rrb->base.BlueBits = 8;
+           rrb->base.AlphaBits = 0;
+           rrb->base.DataType = GL_UNSIGNED_BYTE;
+           break;
        case GL_RGBA8:
            rrb->base._ActualFormat = GL_RGBA8;
            rrb->base._BaseFormat = GL_RGBA;
@@ -287,7 +308,7 @@ radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
            rrb->base.DataType = GL_UNSIGNED_SHORT;
            break;
        case GL_DEPTH_COMPONENT24:
-           rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+           rrb->base._ActualFormat = GL_DEPTH_COMPONENT24;
            rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
            rrb->base.DepthBits = 24;
            rrb->base.DataType = GL_UNSIGNED_INT;
@@ -312,10 +333,8 @@ radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
     rrb->base.AllocStorage = radeon_alloc_window_storage;
     rrb->base.GetPointer = radeon_get_pointer;
 
-    radeonSetSpanFunctions(rrb);
-
     rrb->bo = NULL;
-    return &rrb->base;
+    return rrb;
 }
 
 static struct gl_renderbuffer *
@@ -337,7 +356,6 @@ radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
   return &rrb->base;
 }
 
-
 static void
 radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
                        struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
@@ -356,7 +374,8 @@ radeon_framebuffer_renderbuffer(GLcontext * ctx,
                                GLenum attachment, struct gl_renderbuffer *rb)
 {
 
-   radeonFlush(ctx);
+       if (ctx->Driver.Flush)
+               ctx->Driver.Flush(ctx); /* +r6/r7 */
 
    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
    radeon_draw_buffer(ctx, fb);
@@ -367,49 +386,80 @@ static GLboolean
 radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb, 
                     struct gl_texture_image *texImage)
 {
-   if (texImage->TexFormat == &_mesa_texformat_argb8888) {
-      rrb->base._ActualFormat = GL_RGBA8;
-      rrb->base._BaseFormat = GL_RGBA;
-      rrb->base.DataType = GL_UNSIGNED_BYTE;
-      DBG("Render to RGBA8 texture OK\n");
-   }
-   else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
-      rrb->base._ActualFormat = GL_RGB5;
-      rrb->base._BaseFormat = GL_RGB;
-      rrb->base.DataType = GL_UNSIGNED_SHORT;
-      DBG("Render to RGB5 texture OK\n");
-   }
-   else if (texImage->TexFormat == &_mesa_texformat_z16) {
-      rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
-      rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
-      rrb->base.DataType = GL_UNSIGNED_SHORT;
-      DBG("Render to DEPTH16 texture OK\n");
-   }
-   else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
-      rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
-      rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
-      rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
-      DBG("Render to DEPTH_STENCIL texture OK\n");
-   }
-   else {
-      DBG("Render to texture BAD FORMAT %d\n",
-         texImage->TexFormat->MesaFormat);
-      return GL_FALSE;
-   }
-
-   rrb->base.InternalFormat = rrb->base._ActualFormat;
-   rrb->base.Width = texImage->Width;
-   rrb->base.Height = texImage->Height;
-   rrb->base.RedBits = texImage->TexFormat->RedBits;
-   rrb->base.GreenBits = texImage->TexFormat->GreenBits;
-   rrb->base.BlueBits = texImage->TexFormat->BlueBits;
-   rrb->base.AlphaBits = texImage->TexFormat->AlphaBits;
-   rrb->base.DepthBits = texImage->TexFormat->DepthBits;
-
-   rrb->base.Delete = radeon_delete_renderbuffer;
-   rrb->base.AllocStorage = radeon_nop_alloc_storage;
-
-   return GL_TRUE;
+       int retry = 0;
+restart:
+       if (texImage->TexFormat == &_mesa_texformat_argb8888) {
+               rrb->cpp = 4;
+               rrb->base._ActualFormat = GL_RGBA8;
+               rrb->base._BaseFormat = GL_RGBA;
+               rrb->base.DataType = GL_UNSIGNED_BYTE;
+               DBG("Render to RGBA8 texture OK\n");
+       }
+       else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
+               rrb->cpp = 2;
+               rrb->base._ActualFormat = GL_RGB5;
+               rrb->base._BaseFormat = GL_RGB;
+               rrb->base.DataType = GL_UNSIGNED_BYTE;
+               DBG("Render to RGB5 texture OK\n");
+       }
+       else if (texImage->TexFormat == &_mesa_texformat_argb1555) {
+               rrb->cpp = 2;
+               rrb->base._ActualFormat = GL_RGB5_A1;
+               rrb->base._BaseFormat = GL_RGBA;
+               rrb->base.DataType = GL_UNSIGNED_BYTE;
+               DBG("Render to ARGB1555 texture OK\n");
+       }
+       else if (texImage->TexFormat == &_mesa_texformat_argb4444) {
+               rrb->cpp = 2;
+               rrb->base._ActualFormat = GL_RGBA4;
+               rrb->base._BaseFormat = GL_RGBA;
+               rrb->base.DataType = GL_UNSIGNED_BYTE;
+               DBG("Render to ARGB1555 texture OK\n");
+       }
+       else if (texImage->TexFormat == &_mesa_texformat_z16) {
+               rrb->cpp = 2;
+               rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
+               rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
+               rrb->base.DataType = GL_UNSIGNED_SHORT;
+               DBG("Render to DEPTH16 texture OK\n");
+       }
+       else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
+               rrb->cpp = 4;
+               rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+               rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+               rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+               DBG("Render to DEPTH_STENCIL texture OK\n");
+       }
+       else {
+               /* try redoing the FBO */
+               if (retry == 1) {
+                       DBG("Render to texture BAD FORMAT %d\n",
+                           texImage->TexFormat->MesaFormat);
+                       return GL_FALSE;
+               }
+               texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0,
+                                                               texImage->TexFormat->DataType,
+                                                               1);
+
+               retry++;
+               goto restart;
+       }
+       
+       rrb->pitch = texImage->Width * rrb->cpp;
+       rrb->base.InternalFormat = rrb->base._ActualFormat;
+       rrb->base.Width = texImage->Width;
+       rrb->base.Height = texImage->Height;
+       rrb->base.RedBits = texImage->TexFormat->RedBits;
+       rrb->base.GreenBits = texImage->TexFormat->GreenBits;
+       rrb->base.BlueBits = texImage->TexFormat->BlueBits;
+       rrb->base.AlphaBits = texImage->TexFormat->AlphaBits;
+       rrb->base.DepthBits = texImage->TexFormat->DepthBits;
+       rrb->base.StencilBits = texImage->TexFormat->StencilBits;
+       
+       rrb->base.Delete = radeon_delete_renderbuffer;
+       rrb->base.AllocStorage = radeon_nop_alloc_storage;
+       
+       return GL_TRUE;
 }
 
 
@@ -442,7 +492,74 @@ radeon_render_texture(GLcontext * ctx,
                      struct gl_framebuffer *fb,
                      struct gl_renderbuffer_attachment *att)
 {
+   struct gl_texture_image *newImage
+      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+   struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
+   radeon_texture_image *radeon_image;
+   GLuint imageOffset;
+
+   (void) fb;
+
+   ASSERT(newImage);
+
+   if (newImage->Border != 0) {
+      /* Fallback on drawing to a texture with a border, which won't have a
+       * miptree.
+       */
+      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+      _mesa_render_texture(ctx, fb, att);
+      return;
+   }
+   else if (!rrb) {
+      rrb = radeon_wrap_texture(ctx, newImage);
+      if (rrb) {
+         /* bind the wrapper to the attachment point */
+         _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
+      }
+      else {
+         /* fallback to software rendering */
+         _mesa_render_texture(ctx, fb, att);
+         return;
+      }
+   }
+
+   if (!radeon_update_wrapper(ctx, rrb, newImage)) {
+       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+       _mesa_render_texture(ctx, fb, att);
+       return;
+   }
+
+   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
+       _glthread_GetID(),
+       att->Texture->Name, newImage->Width, newImage->Height,
+       rrb->base.RefCount);
+
+   /* point the renderbufer's region to the texture image region */
+   radeon_image = (radeon_texture_image *)newImage;
+   if (rrb->bo != radeon_image->mt->bo) {
+      if (rrb->bo)
+       radeon_bo_unref(rrb->bo);
+      rrb->bo = radeon_image->mt->bo;
+      radeon_bo_ref(rrb->bo);
+   }
+
+   /* compute offset of the particular 2D image within the texture region */
+   imageOffset = radeon_miptree_image_offset(radeon_image->mt,
+                                            att->CubeMapFace,
+                                            att->TextureLevel);
 
+   if (att->Texture->Target == GL_TEXTURE_3D) {
+      GLuint offsets[6];
+      radeon_miptree_depth_offsets(radeon_image->mt, att->TextureLevel,
+                                  offsets);
+      imageOffset += offsets[att->Zoffset];
+   }
+
+   /* store that offset in the region */
+   rrb->draw_offset = imageOffset;
+
+   /* update drawing region, etc */
+   radeon_draw_buffer(ctx, fb);
 }
 
 static void
@@ -456,14 +573,6 @@ radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
 {
 }
 
-static void
-radeon_blit_framebuffer(GLcontext *ctx,
-                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                       GLbitfield mask, GLenum filter)
-{
-}
-
 void radeon_fbo_init(struct radeon_context *radeon)
 {
   radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
@@ -474,8 +583,17 @@ void radeon_fbo_init(struct radeon_context *radeon)
   radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
   radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
   radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
-  radeon->glCtx->Driver.BlitFramebuffer = radeon_blit_framebuffer;
+  radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_blit_framebuffer;
 }
 
   
-  
+void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
+                               struct radeon_bo *bo)
+{
+  struct radeon_bo *old;
+  old = rb->bo;
+  rb->bo = bo;
+  radeon_bo_ref(bo);
+  if (old)
+    radeon_bo_unref(old);
+}