#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;
}
{
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;
}
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);
}
/* 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;
}
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
+
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);
}
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);
}