gallium: free bitmap fragment shaders, misc clean-up
[mesa.git] / src / mesa / state_tracker / st_cb_fbo.c
index 3cd1fbe851af4761c4000a811fadc27d61f0f929..5384252a8e511dcf57fcbec24649754741ed747a 100644 (file)
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
 #include "st_context.h"
 #include "st_cb_fbo.h"
-#include "st_cb_teximage.h"
+#include "st_cb_texture.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
 
 
-/**
- * Derived renderbuffer class.  Just need to add a pointer to the
- * pipe surface.
- */
-struct st_renderbuffer
-{
-   struct gl_renderbuffer Base;
-#if 0
-   struct pipe_surface *surface;
-#endif
-};
-
 
 /**
- * Cast wrapper.
+ * Compute the renderbuffer's Red/Green/EtcBit fields from the pipe format.
  */
-static INLINE struct st_renderbuffer *
-st_renderbuffer(struct gl_renderbuffer *rb)
+static int
+init_renderbuffer_bits(struct st_renderbuffer *strb,
+                       enum pipe_format pipeFormat)
 {
-   return (struct st_renderbuffer *) rb;
-}
-
+   struct pipe_format_info info;
 
-struct pipe_format_info
-{
-   GLuint format;
-   GLenum base_format;
-   GLubyte red_bits;
-   GLubyte green_bits;
-   GLubyte blue_bits;
-   GLubyte alpha_bits;
-   GLubyte luminance_bits;
-   GLubyte intensity_bits;
-   GLubyte depth_bits;
-   GLubyte stencil_bits;
-   GLubyte size;           /**< in bytes */
-};
-
-
-/*
- * XXX temporary here
- */
-static const struct pipe_format_info *
-pipe_get_format_info(GLuint format)
-{
-   static const struct pipe_format_info info[] = {
-      {
-         PIPE_FORMAT_U_R8_G8_B8_A8,  /* format */
-         GL_RGBA,                    /* base_format */
-         8, 8, 8, 8, 0, 0,           /* color bits */
-         0, 0,                       /* depth, stencil */
-         4                           /* size in bytes */
-      },
-      {
-         PIPE_FORMAT_U_A8_R8_G8_B8,
-         GL_RGBA,                    /* base_format */
-         8, 8, 8, 8, 0, 0,           /* color bits */
-         0, 0,                       /* depth, stencil */
-         4                           /* size in bytes */
-      },
-      {
-         PIPE_FORMAT_U_A1_R5_G5_B5,
-         GL_RGBA,                    /* base_format */
-         5, 5, 5, 1, 0, 0,           /* color bits */
-         0, 0,                       /* depth, stencil */
-         2                           /* size in bytes */
-      },
-      {
-         PIPE_FORMAT_U_R5_G6_B5,
-         GL_RGBA,                    /* base_format */
-         5, 6, 5, 0, 0, 0,           /* color bits */
-         0, 0,                       /* depth, stencil */
-         2                           /* size in bytes */
-      },
-      /* XXX lots more */
-      {
-         PIPE_FORMAT_S8_Z24,
-         GL_DEPTH_STENCIL_EXT,       /* base_format */
-         0, 0, 0, 0, 0, 0,           /* color bits */
-         24, 8,                      /* depth, stencil */
-         4                           /* size in bytes */
-      }
-   };         
-   GLuint i;
-
-   for (i = 0; i < sizeof(info) / sizeof(info[0]); i++) {
-      if (info[i].format == format)
-         return info + i;
+   if (!st_get_format_info( pipeFormat, &info )) {
+      assert( 0 );
    }
-   return NULL;
+
+   strb->Base._ActualFormat = info.base_format;
+   strb->Base.RedBits = info.red_bits;
+   strb->Base.GreenBits = info.green_bits;
+   strb->Base.BlueBits = info.blue_bits;
+   strb->Base.AlphaBits = info.alpha_bits;
+   strb->Base.DepthBits = info.depth_bits;
+   strb->Base.StencilBits = info.stencil_bits;
+   strb->Base.DataType = st_format_datatype(pipeFormat);
+
+   return info.size;
 }
 
 
@@ -149,48 +88,52 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
 {
    struct pipe_context *pipe = ctx->st->pipe;
    struct st_renderbuffer *strb = st_renderbuffer(rb);
-   const GLuint pipeFormat
-      = st_choose_pipe_format(pipe, internalFormat, GL_NONE, GL_NONE);
-   const struct pipe_format_info *info = pipe_get_format_info(pipeFormat);
-   GLuint cpp, pitch;
-
-   if (!info)
-      return GL_FALSE;
-
-   strb->Base._ActualFormat = info->base_format;
-   strb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix */
-   strb->Base.RedBits = info->red_bits;
-   strb->Base.GreenBits = info->green_bits;
-   strb->Base.BlueBits = info->blue_bits;
-   strb->Base.AlphaBits = info->alpha_bits;
-   strb->Base.DepthBits = info->depth_bits;
-   strb->Base.StencilBits = info->stencil_bits;
-
-   cpp = info->size;
-
-   if (!strb->Base.surface) {
-      strb->Base.surface = pipe->surface_alloc(pipe, pipeFormat);
-      if (!strb->Base.surface)
+   enum pipe_format pipeFormat;
+   GLbitfield flags = 0x0; /* XXX needed? */
+
+   if (!strb->surface) {
+      strb->surface = pipe->winsys->surface_alloc(pipe->winsys);
+      assert(strb->surface);
+      assert(strb->surface->refcount);
+      assert(strb->surface->winsys);
+      if (!strb->surface)
          return GL_FALSE;
    }
 
-   /* free old region */
-   if (strb->Base.surface->region) {
-      pipe->region_release(pipe, &strb->Base.surface->region);
+   if (strb->surface->buffer)
+      pipe_buffer_reference(pipe->winsys, &strb->surface->buffer,
+                           NULL);
+
+   /* Determine surface format here */
+   if (strb->format != PIPE_FORMAT_NONE) {
+      assert(strb->format != 0);
+      /* we'll hit this for front/back color bufs */
+      pipeFormat = strb->format;
+   }
+   else {
+      pipeFormat = st_choose_renderbuffer_format(pipe, internalFormat);
    }
 
-   /* Choose a pitch to match hardware requirements:
-    */
-   pitch = ((cpp * width + 63) & ~63) / cpp; /* XXX fix: device-specific */
+   init_renderbuffer_bits(strb, pipeFormat);
 
-   strb->Base.surface->region = pipe->region_alloc(pipe, cpp, pitch, height);
-   if (!strb->Base.surface->region)
+   pipe->winsys->surface_alloc_storage(pipe->winsys,
+                                       strb->surface,
+                                       width,
+                                       height,
+                                       pipeFormat,
+                                       flags);
+   if (!strb->surface->buffer)
       return GL_FALSE; /* out of memory, try s/w buffer? */
 
-   ASSERT(strb->Base.surface->region->buffer);
+   ASSERT(strb->surface->buffer);
+   ASSERT(strb->surface->format);
+   ASSERT(strb->surface->cpp);
+   ASSERT(strb->surface->width == width);
+   ASSERT(strb->surface->height == height);
+   ASSERT(strb->surface->pitch);
 
-   strb->Base.Width  = strb->Base.surface->width  = width;
-   strb->Base.Height = strb->Base.surface->height = height;
+   strb->Base.Width  = width;
+   strb->Base.Height = height;
 
    return GL_TRUE;
 }
@@ -202,15 +145,11 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
 static void
 st_renderbuffer_delete(struct gl_renderbuffer *rb)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct pipe_context *pipe = ctx->st->pipe;
    struct st_renderbuffer *strb = st_renderbuffer(rb);
    ASSERT(strb);
-   if (strb && strb->Base.surface) {
-      if (rb->surface->region) {
-         pipe->region_release(pipe, &strb->Base.surface->region);
-      }
-      free(strb->Base.surface);
+   if (strb->surface) {
+      struct pipe_winsys *ws = strb->surface->winsys;
+      ws->surface_release(ws, &strb->surface);
    }
    free(strb);
 }
@@ -226,7 +165,9 @@ null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
    /* By returning NULL we force all software rendering to go through
     * the span routines.
     */
+#if 0
    assert(0);  /* Should never get called with softpipe */
+#endif
    return NULL;
 }
 
@@ -254,78 +195,79 @@ st_new_renderbuffer(GLcontext *ctx, GLuint name)
       strb->Base.Delete = st_renderbuffer_delete;
       strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
       strb->Base.GetPointer = null_get_pointer;
+      strb->format = PIPE_FORMAT_NONE;
       return &strb->Base;
    }
    return NULL;
 }
 
 
-#if 000
-struct gl_renderbuffer *
-st_new_renderbuffer_fb(struct pipe_region *region, GLuint width, GLuint height)
-{
-   struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
-   if (!strb)
-      return;
-
-   _mesa_init_renderbuffer(&strb->Base, name);
-   strb->Base.Delete = st_renderbuffer_delete;
-   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
-   strb->Base.GetPointer = null_get_pointer;
-   strb->Base.Width = width;
-   strb->Base.Heigth = height;
-
-   strb->region = region;
-
-   return &strb->Base;
-}
-
-#else
-
+/**
+ * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * renderbuffer).  The window system code determines the format.
+ */
 struct gl_renderbuffer *
-st_new_renderbuffer_fb(GLuint intFormat)
+st_new_renderbuffer_fb(enum pipe_format format)
 {
-   struct st_renderbuffer *irb;
+   struct st_renderbuffer *strb;
 
-   irb = CALLOC_STRUCT(st_renderbuffer);
-   if (!irb) {
+   strb = CALLOC_STRUCT(st_renderbuffer);
+   if (!strb) {
       _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
       return NULL;
    }
 
-   _mesa_init_renderbuffer(&irb->Base, 0);
-   irb->Base.ClassID = 0x42; /* XXX temp */
-   irb->Base.InternalFormat = intFormat;
-
-   switch (intFormat) {
-   case GL_RGB5:
-   case GL_RGBA8:
-      irb->Base._BaseFormat = GL_RGBA;
+   _mesa_init_renderbuffer(&strb->Base, 0);
+   strb->Base.ClassID = 0x4242; /* just a unique value */
+   strb->format = format;
+
+   switch (format) {
+   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_A1R5G5B5_UNORM:
+   case PIPE_FORMAT_A4R4G4B4_UNORM:
+   case PIPE_FORMAT_R5G6B5_UNORM:
+      strb->Base.InternalFormat = GL_RGBA;
+      strb->Base._BaseFormat = GL_RGBA;
+      break;
+   case PIPE_FORMAT_Z16_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+      strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   case PIPE_FORMAT_Z32_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+      strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   case PIPE_FORMAT_S8Z24_UNORM:
+   case PIPE_FORMAT_Z24S8_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+      strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
       break;
-   case GL_DEPTH_COMPONENT16:
-      irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+   case PIPE_FORMAT_S8_UNORM:
+      strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+      strb->Base._BaseFormat = GL_STENCIL_INDEX;
       break;
-   case GL_DEPTH24_STENCIL8_EXT:
-      irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+   case PIPE_FORMAT_R16G16B16A16_SNORM:
+      strb->Base.InternalFormat = GL_RGBA16;
+      strb->Base._BaseFormat = GL_RGBA;
       break;
    default:
       _mesa_problem(NULL,
-                   "Unexpected intFormat in st_new_renderbuffer");
+                   "Unexpected format in st_new_renderbuffer_fb");
       return NULL;
    }
 
    /* st-specific methods */
-   irb->Base.Delete = st_renderbuffer_delete;
-   irb->Base.AllocStorage = st_renderbuffer_alloc_storage;
-   irb->Base.GetPointer = null_get_pointer;
-   /* span routines set in alloc_storage function */
+   strb->Base.Delete = st_renderbuffer_delete;
+   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+   strb->Base.GetPointer = null_get_pointer;
 
-   irb->Base.surface = NULL;/*intel_new_surface(intFormat);*/
-   /*irb->Base.surface->rb = irb;*/
+   /* surface is allocated in st_renderbuffer_alloc_storage() */
+   strb->surface = NULL;
 
-   return &irb->Base;
+   return &strb->Base;
 }
-#endif
+
 
 
 
@@ -362,23 +304,54 @@ st_render_texture(GLcontext *ctx,
                   struct gl_renderbuffer_attachment *att)
 {
    struct st_context *st = ctx->st;
-   struct pipe_framebuffer_state framebuffer;
-   struct pipe_surface *texsurface;
+   struct st_renderbuffer *strb;
+   struct gl_renderbuffer *rb;
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_screen *screen = pipe->screen;
+   struct pipe_texture *pt;
+
+   assert(!att->Renderbuffer);
+
+   /* create new renderbuffer which wraps the texture image */
+   rb = st_new_renderbuffer(ctx, 0);
+   if (!rb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
+      return;
+   }
 
-   texsurface = NULL;  /* find the mipmap level, cube face, etc */
+   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+   assert(rb->RefCount == 1);
+   rb->AllocStorage = NULL; /* should not get called */
+   strb = st_renderbuffer(rb);
+
+   /* get the texture for the texture object */
+   pt = st_get_texobj_texture(att->Texture);
+   assert(pt);
+   assert(pt->width[att->TextureLevel]);
+
+   rb->Width = pt->width[att->TextureLevel];
+   rb->Height = pt->height[att->TextureLevel];
+
+   /* the renderbuffer's surface is inside the texture */
+   strb->surface = screen->get_tex_surface(screen, pt,
+                                           att->CubeMapFace,
+                                           att->TextureLevel,
+                                           att->Zoffset);
+   assert(strb->surface);
+
+   init_renderbuffer_bits(strb, pt->format);
 
    /*
-    * XXX basically like this... set the current color (or depth)
-    * drawing surface to be the given texture renderbuffer.
-    */
-   memset(&framebuffer, 0, sizeof(framebuffer));
-   framebuffer.num_cbufs = 1;
-   framebuffer.cbufs[0] = texsurface;
+   printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
+          att->Texture, pt, strb->surface, rb->Width, rb->Height);
+   */
 
-   if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) {
-      st->state.framebuffer = framebuffer;
-      st->pipe->set_framebuffer_state( st->pipe, &framebuffer );
-   }
+   /* Invalidate buffer state so that the pipe's framebuffer state
+    * gets updated.
+    * That's where the new renderbuffer (which we just created) gets
+    * passed to the pipe as a (color/depth) render target.
+    */
+   st_invalidate_state(ctx, _NEW_BUFFERS);
 }
 
 
@@ -389,7 +362,22 @@ static void
 st_finish_render_texture(GLcontext *ctx,
                          struct gl_renderbuffer_attachment *att)
 {
-   /* restore drawing to normal framebuffer. may be a no-op */
+   struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+
+   assert(strb);
+
+   ctx->st->pipe->flush(ctx->st->pipe, PIPE_FLUSH_RENDER_CACHE);
+
+   /*
+   printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+   */
+
+   pipe_surface_reference(&strb->surface, NULL);
+
+   _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+
+   /* restore previous framebuffer state */
+   st_invalidate_state(ctx, _NEW_BUFFERS);
 }