#include "main/fbobject.h"
#include "main/framebuffer.h"
#include "main/macros.h"
+#include "main/mfeatures.h"
#include "main/renderbuffer.h"
#include "pipe/p_context.h"
#include "st_context.h"
#include "st_cb_fbo.h"
#include "st_cb_flush.h"
+#include "st_cb_texture.h"
#include "st_format.h"
#include "st_texture.h"
#include "st_manager.h"
enum pipe_format format;
struct pipe_surface surf_tmpl;
- if (strb->format != PIPE_FORMAT_NONE)
- format = strb->format;
- else
+ if (internalFormat == GL_RGBA16_SNORM && strb->software) {
+ /* Special case for software accum buffers. Otherwise, if the
+ * call to st_choose_renderbuffer_format() fails (because the
+ * driver doesn't support signed 16-bit/channel colors) we'd
+ * just return without allocating the software accum buffer.
+ */
+ format = PIPE_FORMAT_R16G16B16A16_SNORM;
+ }
+ else {
format = st_choose_renderbuffer_format(screen, internalFormat,
rb->NumSamples);
-
+ }
+
+ if (format == PIPE_FORMAT_NONE) {
+ return FALSE;
+ }
+
/* init renderbuffer fields */
strb->Base.Width = width;
strb->Base.Height = height;
strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
+ strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
strb->defined = GL_FALSE; /* undefined contents now */
free(strb->data);
- assert(strb->format != PIPE_FORMAT_NONE);
-
- strb->stride = util_format_get_stride(strb->format, width);
- size = util_format_get_2d_size(strb->format, strb->stride, height);
+ size = _mesa_format_image_size(strb->Base.Format, width, height, 1);
strb->data = malloc(size);
*/
pipe_surface_reference( &strb->surface, NULL );
pipe_resource_reference( &strb->texture, NULL );
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
+
+ if (width == 0 || height == 0) {
+ /* if size is zero, nothing to allocate */
+ return GL_TRUE;
+ }
/* Setup new texture template.
*/
if (util_format_is_depth_or_stencil(format)) {
template.bind = PIPE_BIND_DEPTH_STENCIL;
}
+ else if (strb->Base.Name != 0) {
+ /* this is a user-created renderbuffer */
+ template.bind = PIPE_BIND_RENDER_TARGET;
+ }
else {
+ /* this is a window-system buffer */
template.bind = (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_RENDER_TARGET);
}
if (!strb->texture)
return FALSE;
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
strb->surface = pipe->create_surface(pipe,
strb->texture,
ASSERT(strb);
pipe_surface_reference(&strb->surface, NULL);
pipe_resource_reference(&strb->texture, NULL);
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
free(strb->data);
free(strb);
}
-/**
- * gl_renderbuffer::GetPointer()
- */
-static void *
-null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
- GLint x, GLint y)
-{
- /* 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;
-}
-
-
/**
* Called via ctx->Driver.NewFramebuffer()
*/
{
struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
if (strb) {
+ assert(name != 0);
_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->format = PIPE_FORMAT_NONE;
return &strb->Base;
}
return NULL;
strb->Base.ClassID = 0x4242; /* just a unique value */
strb->Base.NumSamples = samples;
strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
- strb->format = format;
+ strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
strb->software = sw;
switch (format) {
case PIPE_FORMAT_Z32_UNORM:
strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
break;
- case PIPE_FORMAT_S8_USCALED:
+ case PIPE_FORMAT_S8_UINT:
strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
break;
case PIPE_FORMAT_R16G16B16A16_SNORM:
- strb->Base.InternalFormat = GL_RGBA16;
+ /* accum buffer */
+ strb->Base.InternalFormat = GL_RGBA16_SNORM;
break;
case PIPE_FORMAT_R8_UNORM:
strb->Base.InternalFormat = GL_R8;
case PIPE_FORMAT_R16G16_UNORM:
strb->Base.InternalFormat = GL_RG16;
break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ strb->Base.InternalFormat = GL_RGBA32F;
+ break;
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ strb->Base.InternalFormat = GL_RGBA16F;
+ break;
default:
_mesa_problem(NULL,
- "Unexpected format in st_new_renderbuffer_fb");
+ "Unexpected format %s in st_new_renderbuffer_fb",
+ util_format_name(format));
free(strb);
return NULL;
}
/* st-specific methods */
strb->Base.Delete = st_renderbuffer_delete;
strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
- strb->Base.GetPointer = null_get_pointer;
/* surface is allocated in st_renderbuffer_alloc_storage() */
strb->surface = NULL;
}
-
-
/**
* Called via ctx->Driver.BindFramebufferEXT().
*/
st_bind_framebuffer(struct gl_context *ctx, GLenum target,
struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
{
-
-}
-
-/**
- * Called by ctx->Driver.FramebufferRenderbuffer
- */
-static void
-st_framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment,
- struct gl_renderbuffer *rb)
-{
- /* XXX no need for derivation? */
- _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+ /* no-op */
}
struct pipe_context *pipe = st->pipe;
struct st_renderbuffer *strb;
struct gl_renderbuffer *rb;
- struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
+ struct pipe_resource *pt;
struct st_texture_object *stObj;
const struct gl_texture_image *texImage;
struct pipe_surface surf_tmpl;
- /* When would this fail? Perhaps assert? */
- if (!pt)
+ if (!st_finalize_texture(ctx, pipe, att->Texture))
return;
+ pt = st_get_texobj_resource(att->Texture);
+ assert(pt);
+
/* get pointer to texture image we're rendeing to */
- texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ texImage = _mesa_get_attachment_teximage(att);
- /* create new renderbuffer which wraps the texture image */
- rb = st_new_renderbuffer(ctx, 0);
+ /* create new renderbuffer which wraps the texture image.
+ * Use the texture's name as the renderbuffer's name so that we have
+ * something that's non-zero (to determine vertical orientation) and
+ * possibly helpful for debugging.
+ */
+ rb = st_new_renderbuffer(ctx, att->Texture->Name);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
return;
rb->Width = texImage->Width2;
rb->Height = texImage->Height2;
rb->_BaseFormat = texImage->_BaseFormat;
- /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
-
- /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
+ rb->InternalFormat = texImage->InternalFormat;
pipe_resource_reference( &strb->texture, pt );
pipe_surface_reference(&strb->surface, NULL);
- pipe_sampler_view_reference(&strb->sampler_view,
- st_get_texture_sampler_view(stObj, pipe));
-
assert(strb->rtt_level <= strb->texture->last_level);
/* new surface for rendering into the texture */
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = strb->texture->format;
+ surf_tmpl.format = ctx->Color.sRGBEnabled
+ ? strb->texture->format : util_format_linear(strb->texture->format);
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = strb->rtt_level;
surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
strb->texture,
&surf_tmpl);
- strb->format = pt->format;
-
strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
- strb->Base.DataType = st_format_datatype(pt->format);
-
- /*
- printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
- att->Texture, pt, strb->surface, rb->Width, rb->Height);
- */
/* Invalidate buffer state so that the pipe's framebuffer state
* gets updated.
st_finish_render_texture(struct gl_context *ctx,
struct gl_renderbuffer_attachment *att)
{
- struct st_context *st = st_context(ctx);
struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
if (!strb)
return;
- st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
strb->rtt = NULL;
- /*
- printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
- */
-
/* restore previous framebuffer state */
st_invalidate_state(ctx, _NEW_BUFFERS);
}
* Validate a renderbuffer attachment for a particular set of bindings.
*/
static GLboolean
-st_validate_attachment(struct pipe_screen *screen,
+st_validate_attachment(struct gl_context *ctx,
+ struct pipe_screen *screen,
const struct gl_renderbuffer_attachment *att,
unsigned bindings)
{
const struct st_texture_object *stObj = st_texture_object(att->Texture);
+ enum pipe_format format;
+ gl_format texFormat;
/* Only validate texture attachments for now, since
* st_renderbuffer_alloc_storage makes sure that
if (!stObj)
return GL_FALSE;
- return screen->is_format_supported(screen, stObj->pt->format,
+ format = stObj->pt->format;
+ texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;
+
+ /* If the encoding is sRGB and sRGB rendering cannot be enabled,
+ * check for linear format support instead.
+ * Later when we create a surface, we change the format to a linear one. */
+ if (!ctx->Extensions.EXT_framebuffer_sRGB &&
+ _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
+ const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
+ format = st_mesa_format_to_pipe_format(linearFormat);
+ }
+
+ return screen->is_format_supported(screen, format,
PIPE_TEXTURE_2D,
- stObj->pt->nr_samples, bindings, 0);
+ stObj->pt->nr_samples, bindings);
}
const struct gl_renderbuffer_attachment *stencil =
&fb->Attachment[BUFFER_STENCIL];
GLuint i;
+ enum pipe_format first_format = PIPE_FORMAT_NONE;
+ boolean mixed_formats =
+ screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
- if (!st_validate_attachment(screen,
+ if (!st_validate_attachment(ctx,
+ screen,
depth,
PIPE_BIND_DEPTH_STENCIL)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
- if (!st_validate_attachment(screen,
+ if (!st_validate_attachment(ctx,
+ screen,
stencil,
PIPE_BIND_DEPTH_STENCIL)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
- if (!st_validate_attachment(screen,
- &fb->Attachment[BUFFER_COLOR0 + i],
+ struct gl_renderbuffer_attachment *att =
+ &fb->Attachment[BUFFER_COLOR0 + i];
+ enum pipe_format format;
+
+ if (!st_validate_attachment(ctx,
+ screen,
+ att,
PIPE_BIND_RENDER_TARGET)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
+
+ if (!mixed_formats) {
+ /* Disallow mixed formats. */
+ if (att->Type != GL_NONE) {
+ format = st_renderbuffer(att->Renderbuffer)->surface->format;
+ } else {
+ continue;
+ }
+
+ if (first_format == PIPE_FORMAT_NONE) {
+ first_format = format;
+ } else if (format != first_format) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ }
}
}
}
+
+/**
+ * Called via ctx->Driver.MapRenderbuffer.
+ */
+static void
+st_MapRenderbuffer(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint x, GLuint y, GLuint w, GLuint h,
+ GLbitfield mode,
+ GLubyte **mapOut, GLint *rowStrideOut)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ struct pipe_context *pipe = st->pipe;
+ const GLboolean invert = rb->Name == 0;
+ unsigned usage;
+ GLuint y2;
+
+ if (strb->software) {
+ /* software-allocated renderbuffer (probably an accum buffer) */
+ if (strb->data) {
+ GLint bpp = _mesa_get_format_bytes(strb->Base.Format);
+ GLint stride = _mesa_format_row_stride(strb->Base.Format,
+ strb->Base.Width);
+ *mapOut = (GLubyte *) strb->data + y * stride + x * bpp;
+ *rowStrideOut = stride;
+ }
+ else {
+ *mapOut = NULL;
+ *rowStrideOut = 0;
+ }
+ return;
+ }
+
+ usage = 0x0;
+ if (mode & GL_MAP_READ_BIT)
+ usage |= PIPE_TRANSFER_READ;
+ if (mode & GL_MAP_WRITE_BIT)
+ usage |= PIPE_TRANSFER_WRITE;
+ if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
+ usage |= PIPE_TRANSFER_DISCARD_RANGE;
+
+ /* Note: y=0=bottom of buffer while y2=0=top of buffer.
+ * 'invert' will be true for window-system buffers and false for
+ * user-allocated renderbuffers and textures.
+ */
+ if (invert)
+ y2 = strb->Base.Height - y - h;
+ else
+ y2 = y;
+
+ strb->transfer = pipe_get_transfer(pipe,
+ strb->texture,
+ strb->rtt_level,
+ strb->rtt_face + strb->rtt_slice,
+ usage, x, y2, w, h);
+ if (strb->transfer) {
+ GLubyte *map = pipe_transfer_map(pipe, strb->transfer);
+ if (invert) {
+ *rowStrideOut = -strb->transfer->stride;
+ map += (h - 1) * strb->transfer->stride;
+ }
+ else {
+ *rowStrideOut = strb->transfer->stride;
+ }
+ *mapOut = map;
+ }
+ else {
+ *mapOut = NULL;
+ *rowStrideOut = 0;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.UnmapRenderbuffer.
+ */
+static void
+st_UnmapRenderbuffer(struct gl_context *ctx,
+ struct gl_renderbuffer *rb)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ struct pipe_context *pipe = st->pipe;
+
+ if (strb->software) {
+ /* software-allocated renderbuffer (probably an accum buffer) */
+ return;
+ }
+
+ pipe_transfer_unmap(pipe, strb->transfer);
+ pipe->transfer_destroy(pipe, strb->transfer);
+ strb->transfer = NULL;
+}
+
+
+
void st_init_fbo_functions(struct dd_function_table *functions)
{
#if FEATURE_EXT_framebuffer_object
functions->NewFramebuffer = st_new_framebuffer;
functions->NewRenderbuffer = st_new_renderbuffer;
functions->BindFramebuffer = st_bind_framebuffer;
- functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+ functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
functions->RenderTexture = st_render_texture;
functions->FinishRenderTexture = st_finish_render_texture;
functions->ValidateFramebuffer = st_validate_framebuffer;
#endif
- /* no longer needed by core Mesa, drivers handle resizes...
- functions->ResizeBuffers = st_resize_buffers;
- */
functions->DrawBuffers = st_DrawBuffers;
functions->ReadBuffer = st_ReadBuffer;
+
+ functions->MapRenderbuffer = st_MapRenderbuffer;
+ functions->UnmapRenderbuffer = st_UnmapRenderbuffer;
}
-/* XXX unused ? */
-struct pipe_sampler_view *
-st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
- struct pipe_context *pipe)
-{
- if (!rb->sampler_view) {
- rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
- }
- return rb->sampler_view;
-}