From eaedc21febeadad4cf0e370f5d97e7bdb4470870 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 5 Apr 2011 09:51:44 +0000 Subject: xserver xkeyboard-config libxcb xkbcomp mesa git update 5 Apr 2011 --- mesalib/src/mesa/main/renderbuffer.c | 15 +- mesalib/src/mesa/main/texformat.c | 26 +- mesalib/src/mesa/state_tracker/st_cb_fbo.c | 1307 ++++++++++++++-------------- mesalib/src/mesa/state_tracker/st_draw.c | 127 +-- 4 files changed, 771 insertions(+), 704 deletions(-) (limited to 'mesalib/src') diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index 67ee589d7..e6d5fe4bf 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -1122,7 +1122,20 @@ _mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer * rb->Width = width; rb->Height = height; rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); - ASSERT(rb->_BaseFormat); + + if (rb->Name == 0 && + internalFormat == GL_RGBA16_SNORM && + rb->_BaseFormat == 0) { + /* NOTE: This is a special case just for accumulation buffers. + * This is a very limited use case- there's no snorm texturing or + * rendering going on. + */ + rb->_BaseFormat = GL_RGBA; + } + else { + /* the internalFormat should have been error checked long ago */ + ASSERT(rb->_BaseFormat); + } return GL_TRUE; } diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 8b7b4ff47..da907455b 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -402,7 +402,7 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, case GL_RGB_SNORM: case GL_RGB8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); - break; + /* FALLTHROUGH */ case GL_RGBA_SNORM: case GL_RGBA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); @@ -411,18 +411,27 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, case GL_ALPHA_SNORM: case GL_ALPHA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE_SNORM: case GL_LUMINANCE8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE_ALPHA_SNORM: case GL_LUMINANCE8_ALPHA8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL88); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_INTENSITY_SNORM: case GL_INTENSITY8_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I8); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_R16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R16); @@ -432,21 +441,32 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, break; case GL_RGB16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16); - break; + /* FALLTHROUGH */ case GL_RGBA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_ALPHA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_A16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_LUMINANCE16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L16); - break; + /* FALLTHROUGH */ case GL_LUMINANCE16_ALPHA16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_AL1616); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; case GL_INTENSITY16_SNORM: RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_I16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888); + RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV); break; default: ; /* fall-through */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index fe67b03b2..7ffee901c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -1,642 +1,665 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * Framebuffer/renderbuffer functions. - * - * \author Brian Paul - */ - - -#include "main/imports.h" -#include "main/context.h" -#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 "pipe/p_defines.h" -#include "pipe/p_screen.h" -#include "st_context.h" -#include "st_cb_fbo.h" -#include "st_cb_flush.h" -#include "st_format.h" -#include "st_texture.h" -#include "st_manager.h" - -#include "util/u_format.h" -#include "util/u_inlines.h" -#include "util/u_surface.h" - - -/** - * gl_renderbuffer::AllocStorage() - * This is called to allocate the original drawing surface, and - * during window resize. - */ -static GLboolean -st_renderbuffer_alloc_storage(struct gl_context * ctx, - struct gl_renderbuffer *rb, - GLenum internalFormat, - GLuint width, GLuint height) -{ - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = st->pipe->screen; - struct st_renderbuffer *strb = st_renderbuffer(rb); - enum pipe_format format; - struct pipe_surface surf_tmpl; - - if (strb->format != PIPE_FORMAT_NONE) - format = strb->format; - 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._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); - strb->Base.DataType = st_format_datatype(format); - - strb->defined = GL_FALSE; /* undefined contents now */ - - if (strb->software) { - size_t size; - - 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); - - strb->data = malloc(size); - - return strb->data != NULL; - } - else { - struct pipe_resource template; - - /* Free the old surface and texture - */ - pipe_surface_reference( &strb->surface, NULL ); - pipe_resource_reference( &strb->texture, NULL ); - pipe_sampler_view_reference(&strb->sampler_view, NULL); - - /* Setup new texture template. - */ - memset(&template, 0, sizeof(template)); - template.target = st->internal_target; - template.format = format; - template.width0 = width; - template.height0 = height; - template.depth0 = 1; - template.array_size = 1; - template.last_level = 0; - template.nr_samples = rb->NumSamples; - if (util_format_is_depth_or_stencil(format)) { - template.bind = PIPE_BIND_DEPTH_STENCIL; - } - else { - template.bind = (PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_RENDER_TARGET); - } - - strb->texture = screen->resource_create(screen, &template); - - 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, - &surf_tmpl); - if (strb->surface) { - assert(strb->surface->texture); - assert(strb->surface->format); - assert(strb->surface->width == width); - assert(strb->surface->height == height); - } - - return strb->surface != NULL; - } -} - - -/** - * gl_renderbuffer::Delete() - */ -static void -st_renderbuffer_delete(struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *strb = st_renderbuffer(rb); - 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() - */ -static struct gl_framebuffer * -st_new_framebuffer(struct gl_context *ctx, GLuint name) -{ - /* XXX not sure we need to subclass gl_framebuffer for pipe */ - return _mesa_new_framebuffer(ctx, name); -} - - -/** - * Called via ctx->Driver.NewRenderbuffer() - */ -static struct gl_renderbuffer * -st_new_renderbuffer(struct gl_context *ctx, GLuint name) -{ - struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer); - if (strb) { - _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; -} - - -/** - * 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(enum pipe_format format, int samples, boolean sw) -{ - struct st_renderbuffer *strb; - - strb = ST_CALLOC_STRUCT(st_renderbuffer); - if (!strb) { - _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); - return NULL; - } - - _mesa_init_renderbuffer(&strb->Base, 0); - strb->Base.ClassID = 0x4242; /* just a unique value */ - strb->Base.NumSamples = samples; - strb->Base.Format = st_pipe_format_to_mesa_format(format); - strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); - strb->Base.DataType = st_format_datatype(format); - strb->format = format; - strb->software = sw; - - switch (format) { - case PIPE_FORMAT_R8G8B8A8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_R8G8B8X8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_B5G5R5A1_UNORM: - case PIPE_FORMAT_B4G4R4A4_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - strb->Base.InternalFormat = GL_RGBA; - break; - case PIPE_FORMAT_Z16_UNORM: - strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; - break; - 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_Z24X8_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; - break; - case PIPE_FORMAT_S8_USCALED: - strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; - break; - case PIPE_FORMAT_R16G16B16A16_SNORM: - strb->Base.InternalFormat = GL_RGBA16; - break; - case PIPE_FORMAT_R8_UNORM: - strb->Base.InternalFormat = GL_R8; - break; - case PIPE_FORMAT_R8G8_UNORM: - strb->Base.InternalFormat = GL_RG8; - break; - case PIPE_FORMAT_R16_UNORM: - strb->Base.InternalFormat = GL_R16; - break; - case PIPE_FORMAT_R16G16_UNORM: - strb->Base.InternalFormat = GL_RG16; - break; - default: - _mesa_problem(NULL, - "Unexpected format in st_new_renderbuffer_fb"); - 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; - - return &strb->Base; -} - - - - -/** - * Called via ctx->Driver.BindFramebufferEXT(). - */ -static void -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); -} - - -/** - * Called by ctx->Driver.RenderTexture - */ -static void -st_render_texture(struct gl_context *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att) -{ - struct st_context *st = st_context(ctx); - 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 st_texture_object *stObj; - const struct gl_texture_image *texImage; - struct pipe_surface surf_tmpl; - - /* When would this fail? Perhaps assert? */ - if (!pt) - return; - - /* get pointer to texture image we're rendeing to */ - texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; - - /* 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; - } - - _mesa_reference_renderbuffer(&att->Renderbuffer, rb); - assert(rb->RefCount == 1); - rb->AllocStorage = NULL; /* should not get called */ - strb = st_renderbuffer(rb); - - assert(strb->Base.RefCount > 0); - - /* get the texture for the texture object */ - stObj = st_texture_object(att->Texture); - - /* point renderbuffer at texobject */ - strb->rtt = stObj; - strb->rtt_level = att->TextureLevel; - strb->rtt_face = att->CubeMapFace; - strb->rtt_slice = att->Zoffset; - - 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);*/ - - 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 = 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; - surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; - strb->surface = pipe->create_surface(pipe, - 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. - * 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); -} - - -/** - * Called via ctx->Driver.FinishRenderTexture. - */ -static void -st_finish_render_texture(struct gl_context *ctx, - struct gl_renderbuffer_attachment *att) -{ - struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); - - if (!strb) - return; - - 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 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 - * the format is supported. - */ - if (att->Type != GL_TEXTURE) - return GL_TRUE; - - if (!stObj) - return GL_FALSE; - - format = stObj->pt->format; - texFormat = - stObj->base.Image[att->CubeMapFace][att->TextureLevel]->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->Const.sRGBCapable && - _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); -} - - -/** - * Check if two renderbuffer attachments name a combined depth/stencil - * renderbuffer. - */ -GLboolean -st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, - const struct gl_renderbuffer_attachment *stencil) -{ - assert(depth && stencil); - - if (depth->Type == stencil->Type) { - if (depth->Type == GL_RENDERBUFFER_EXT && - depth->Renderbuffer == stencil->Renderbuffer) - return GL_TRUE; - - if (depth->Type == GL_TEXTURE && - depth->Texture == stencil->Texture) - return GL_TRUE; - } - - return GL_FALSE; -} - - -/** - * Check that the framebuffer configuration is valid in terms of what - * the driver can support. - * - * For Gallium we only supports combined Z+stencil, not separate buffers. - */ -static void -st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; - const struct gl_renderbuffer_attachment *depth = - &fb->Attachment[BUFFER_DEPTH]; - const struct gl_renderbuffer_attachment *stencil = - &fb->Attachment[BUFFER_STENCIL]; - GLuint i; - - if (depth->Type && stencil->Type && depth->Type != stencil->Type) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - return; - } - if (depth->Type == GL_RENDERBUFFER_EXT && - stencil->Type == GL_RENDERBUFFER_EXT && - depth->Renderbuffer != stencil->Renderbuffer) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - return; - } - if (depth->Type == GL_TEXTURE && - stencil->Type == GL_TEXTURE && - depth->Texture != stencil->Texture) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - return; - } - - if (!st_validate_attachment(ctx, - screen, - depth, - PIPE_BIND_DEPTH_STENCIL)) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - return; - } - 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(ctx, - screen, - &fb->Attachment[BUFFER_COLOR0 + i], - PIPE_BIND_RENDER_TARGET)) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - return; - } - } -} - - -/** - * Called via glDrawBuffer. - */ -static void -st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers) -{ - struct st_context *st = st_context(ctx); - struct gl_framebuffer *fb = ctx->DrawBuffer; - GLuint i; - - (void) count; - (void) buffers; - - /* add the renderbuffers on demand */ - for (i = 0; i < fb->_NumColorDrawBuffers; i++) { - gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i]; - st_manager_add_color_renderbuffer(st, fb, idx); - } -} - - -/** - * Called via glReadBuffer. - */ -static void -st_ReadBuffer(struct gl_context *ctx, GLenum buffer) -{ - struct st_context *st = st_context(ctx); - struct gl_framebuffer *fb = ctx->ReadBuffer; - - (void) buffer; - - /* add the renderbuffer on demand */ - st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex); -} - - -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->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; -} - -/* 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; -} +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * Framebuffer/renderbuffer functions. + * + * \author Brian Paul + */ + + +#include "main/imports.h" +#include "main/context.h" +#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 "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "st_context.h" +#include "st_cb_fbo.h" +#include "st_cb_flush.h" +#include "st_format.h" +#include "st_texture.h" +#include "st_manager.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" + + +/** + * gl_renderbuffer::AllocStorage() + * This is called to allocate the original drawing surface, and + * during window resize. + */ +static GLboolean +st_renderbuffer_alloc_storage(struct gl_context * ctx, + struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = st->pipe->screen; + struct st_renderbuffer *strb = st_renderbuffer(rb); + enum pipe_format format; + struct pipe_surface surf_tmpl; + + if (strb->format != PIPE_FORMAT_NONE) + format = strb->format; + 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._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); + strb->Base.DataType = st_format_datatype(format); + + strb->defined = GL_FALSE; /* undefined contents now */ + + if (strb->software) { + size_t size; + + 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); + + strb->data = malloc(size); + + return strb->data != NULL; + } + else { + struct pipe_resource template; + + /* Free the old surface and texture + */ + pipe_surface_reference( &strb->surface, NULL ); + pipe_resource_reference( &strb->texture, NULL ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + + /* Setup new texture template. + */ + memset(&template, 0, sizeof(template)); + template.target = st->internal_target; + template.format = format; + template.width0 = width; + template.height0 = height; + template.depth0 = 1; + template.array_size = 1; + template.last_level = 0; + template.nr_samples = rb->NumSamples; + if (util_format_is_depth_or_stencil(format)) { + template.bind = PIPE_BIND_DEPTH_STENCIL; + } + else { + template.bind = (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET); + } + + strb->texture = screen->resource_create(screen, &template); + + 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, + &surf_tmpl); + if (strb->surface) { + assert(strb->surface->texture); + assert(strb->surface->format); + assert(strb->surface->width == width); + assert(strb->surface->height == height); + } + + return strb->surface != NULL; + } +} + + +/** + * gl_renderbuffer::Delete() + */ +static void +st_renderbuffer_delete(struct gl_renderbuffer *rb) +{ + struct st_renderbuffer *strb = st_renderbuffer(rb); + 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() + */ +static struct gl_framebuffer * +st_new_framebuffer(struct gl_context *ctx, GLuint name) +{ + /* XXX not sure we need to subclass gl_framebuffer for pipe */ + return _mesa_new_framebuffer(ctx, name); +} + + +/** + * Called via ctx->Driver.NewRenderbuffer() + */ +static struct gl_renderbuffer * +st_new_renderbuffer(struct gl_context *ctx, GLuint name) +{ + struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer); + if (strb) { + _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; +} + + +/** + * 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(enum pipe_format format, int samples, boolean sw) +{ + struct st_renderbuffer *strb; + + strb = ST_CALLOC_STRUCT(st_renderbuffer); + if (!strb) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(&strb->Base, 0); + strb->Base.ClassID = 0x4242; /* just a unique value */ + strb->Base.NumSamples = samples; + strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); + strb->Base.DataType = st_format_datatype(format); + strb->format = format; + strb->software = sw; + + switch (format) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B5G6R5_UNORM: + strb->Base.InternalFormat = GL_RGBA; + break; + case PIPE_FORMAT_Z16_UNORM: + strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; + break; + 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_Z24X8_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; + break; + case PIPE_FORMAT_S8_USCALED: + strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; + break; + case PIPE_FORMAT_R16G16B16A16_SNORM: + strb->Base.InternalFormat = GL_RGBA16; + break; + case PIPE_FORMAT_R8_UNORM: + strb->Base.InternalFormat = GL_R8; + break; + case PIPE_FORMAT_R8G8_UNORM: + strb->Base.InternalFormat = GL_RG8; + break; + case PIPE_FORMAT_R16_UNORM: + strb->Base.InternalFormat = GL_R16; + break; + case PIPE_FORMAT_R16G16_UNORM: + strb->Base.InternalFormat = GL_RG16; + break; + default: + _mesa_problem(NULL, + "Unexpected format in st_new_renderbuffer_fb"); + 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; + + return &strb->Base; +} + + + + +/** + * Called via ctx->Driver.BindFramebufferEXT(). + */ +static void +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); +} + + +/** + * Called by ctx->Driver.RenderTexture + */ +static void +st_render_texture(struct gl_context *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ + struct st_context *st = st_context(ctx); + 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 st_texture_object *stObj; + const struct gl_texture_image *texImage; + struct pipe_surface surf_tmpl; + + /* When would this fail? Perhaps assert? */ + if (!pt) + return; + + /* get pointer to texture image we're rendeing to */ + texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + + /* 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; + } + + _mesa_reference_renderbuffer(&att->Renderbuffer, rb); + assert(rb->RefCount == 1); + rb->AllocStorage = NULL; /* should not get called */ + strb = st_renderbuffer(rb); + + assert(strb->Base.RefCount > 0); + + /* get the texture for the texture object */ + stObj = st_texture_object(att->Texture); + + /* point renderbuffer at texobject */ + strb->rtt = stObj; + strb->rtt_level = att->TextureLevel; + strb->rtt_face = att->CubeMapFace; + strb->rtt_slice = att->Zoffset; + + 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);*/ + + 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 = 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; + surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; + strb->surface = pipe->create_surface(pipe, + 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. + * 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); +} + + +/** + * Called via ctx->Driver.FinishRenderTexture. + */ +static void +st_finish_render_texture(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att) +{ + struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); + + if (!strb) + return; + + 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 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 + * the format is supported. + */ + if (att->Type != GL_TEXTURE) + return GL_TRUE; + + if (!stObj) + return GL_FALSE; + + format = stObj->pt->format; + texFormat = + stObj->base.Image[att->CubeMapFace][att->TextureLevel]->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->Const.sRGBCapable && + _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); +} + + +/** + * Check if two renderbuffer attachments name a combined depth/stencil + * renderbuffer. + */ +GLboolean +st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, + const struct gl_renderbuffer_attachment *stencil) +{ + assert(depth && stencil); + + if (depth->Type == stencil->Type) { + if (depth->Type == GL_RENDERBUFFER_EXT && + depth->Renderbuffer == stencil->Renderbuffer) + return GL_TRUE; + + if (depth->Type == GL_TEXTURE && + depth->Texture == stencil->Texture) + return GL_TRUE; + } + + return GL_FALSE; +} + + +/** + * Check that the framebuffer configuration is valid in terms of what + * the driver can support. + * + * For Gallium we only supports combined Z+stencil, not separate buffers. + */ +static void +st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + struct st_context *st = st_context(ctx); + struct pipe_screen *screen = st->pipe->screen; + const struct gl_renderbuffer_attachment *depth = + &fb->Attachment[BUFFER_DEPTH]; + 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 (depth->Type == GL_RENDERBUFFER_EXT && + stencil->Type == GL_RENDERBUFFER_EXT && + depth->Renderbuffer != stencil->Renderbuffer) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + if (depth->Type == GL_TEXTURE && + stencil->Type == GL_TEXTURE && + depth->Texture != stencil->Texture) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + + if (!st_validate_attachment(ctx, + screen, + depth, + PIPE_BIND_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + 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++) { + 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 glDrawBuffer. + */ +static void +st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers) +{ + struct st_context *st = st_context(ctx); + struct gl_framebuffer *fb = ctx->DrawBuffer; + GLuint i; + + (void) count; + (void) buffers; + + /* add the renderbuffers on demand */ + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i]; + st_manager_add_color_renderbuffer(st, fb, idx); + } +} + + +/** + * Called via glReadBuffer. + */ +static void +st_ReadBuffer(struct gl_context *ctx, GLenum buffer) +{ + struct st_context *st = st_context(ctx); + struct gl_framebuffer *fb = ctx->ReadBuffer; + + (void) buffer; + + /* add the renderbuffer on demand */ + st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex); +} + + +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->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; +} + +/* 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; +} diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 40afa4362..487f3f19c 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -181,7 +181,7 @@ static GLuint fixed_types[4] = { /** * Return a PIPE_FORMAT_x for the given GL datatype and size. */ -GLuint +enum pipe_format st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, GLboolean normalized) { @@ -211,7 +211,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; case GL_FIXED: return fixed_types[size-1]; default: assert(0); return 0; - } + } } else { switch (type) { @@ -226,15 +226,13 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; case GL_FIXED: return fixed_types[size-1]; default: assert(0); return 0; - } + } } - return 0; /* silence compiler warning */ + return PIPE_FORMAT_NONE; /* silence compiler warning */ } - - /** * Examine the active arrays to determine if we have interleaved * vertex arrays all living in one VBO, or all living in user space. @@ -253,8 +251,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp, for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj; - const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */ + const struct gl_client_array *array = arrays[mesaAttr]; + const struct gl_buffer_object *bufObj = array->BufferObj; + const GLsizei stride = array->StrideB; /* in bytes */ if (firstStride < 0) { firstStride = stride; @@ -272,9 +271,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp, return GL_FALSE; } if (!client_addr) { - client_addr = arrays[mesaAttr]->Ptr; + client_addr = array->Ptr; } - else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) { + else if (abs(array->Ptr - client_addr) > firstStride) { /* arrays start too far apart */ return GL_FALSE; } @@ -315,8 +314,8 @@ setup_interleaved_attribs(struct gl_context *ctx, GLuint attr; const GLubyte *low_addr = NULL; - /* Find the lowest address. */ - if(vpv->num_inputs) { + /* Find the lowest address of the arrays we're drawing */ + if (vpv->num_inputs) { low_addr = arrays[vp->index_to_input[0]]->Ptr; for (attr = 1; attr < vpv->num_inputs; attr++) { @@ -327,22 +326,24 @@ setup_interleaved_attribs(struct gl_context *ctx, for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; - struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; + const struct gl_client_array *array = arrays[mesaAttr]; + struct gl_buffer_object *bufobj = array->BufferObj; struct st_buffer_object *stobj = st_buffer_object(bufobj); - GLsizei stride = arrays[mesaAttr]->StrideB; + GLsizei stride = array->StrideB; if (attr == 0) { if (bufobj && bufobj->Name) { vbuffer->buffer = NULL; pipe_resource_reference(&vbuffer->buffer, stobj->buffer); vbuffer->buffer_offset = pointer_to_offset(low_addr); - } else { - uint divisor = arrays[mesaAttr]->InstanceDivisor; + } + else { + uint divisor = array->InstanceDivisor; uint length = (divisor ? num_instances / divisor : max_index) + 1; - vbuffer->buffer = - pipe_user_buffer_create(pipe->screen, (void*)low_addr, - stride * length, - PIPE_BIND_VERTEX_BUFFER); + vbuffer->buffer = pipe_user_buffer_create(pipe->screen, + (void*) low_addr, + stride * length, + PIPE_BIND_VERTEX_BUFFER); vbuffer->buffer_offset = 0; /* Track user vertex buffers. */ @@ -353,15 +354,13 @@ setup_interleaved_attribs(struct gl_context *ctx, vbuffer->stride = stride; /* in bytes */ } - velements[attr].src_offset = - (unsigned) (arrays[mesaAttr]->Ptr - low_addr); - velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; + velements[attr].src_offset = (unsigned) (array->Ptr - low_addr); + velements[attr].instance_divisor = array->InstanceDivisor; velements[attr].vertex_buffer_index = 0; - velements[attr].src_format = - st_pipe_vertex_format(arrays[mesaAttr]->Type, - arrays[mesaAttr]->Size, - arrays[mesaAttr]->Format, - arrays[mesaAttr]->Normalized); + velements[attr].src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized); assert(velements[attr].src_format); } } @@ -389,8 +388,9 @@ setup_non_interleaved_attribs(struct gl_context *ctx, for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; - struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; - GLsizei stride = arrays[mesaAttr]->StrideB; + const struct gl_client_array *array = arrays[mesaAttr]; + struct gl_buffer_object *bufobj = array->BufferObj; + GLsizei stride = array->StrideB; if (bufobj && bufobj->Name) { /* Attribute data is in a VBO. @@ -402,30 +402,39 @@ setup_non_interleaved_attribs(struct gl_context *ctx, vbuffer[attr].buffer = NULL; pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer); - vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); + vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr); } else { /* wrap user data */ - if (arrays[mesaAttr]->Ptr) { - uint divisor = arrays[mesaAttr]->InstanceDivisor; - uint length = (divisor ? num_instances / divisor : max_index) + 1; - vbuffer[attr].buffer = - pipe_user_buffer_create(pipe->screen, - (void *) arrays[mesaAttr]->Ptr, - stride * length, - PIPE_BIND_VERTEX_BUFFER); + uint bytes; + void *ptr; + + if (array->Ptr) { + if (stride == 0) { + bytes = _mesa_sizeof_type(array->Type) * array->Size; + } + else { + uint divisor = array->InstanceDivisor; + uint length = (divisor ? num_instances / divisor : max_index) + 1; + bytes = stride * length; + } + + ptr = (void *) array->Ptr; } else { /* no array, use ctx->Current.Attrib[] value */ - uint bytes = sizeof(ctx->Current.Attrib[0]); - vbuffer[attr].buffer = - pipe_user_buffer_create(pipe->screen, - (void *) ctx->Current.Attrib[mesaAttr], - bytes, - PIPE_BIND_VERTEX_BUFFER); + bytes = sizeof(ctx->Current.Attrib[0]); + ptr = (void *) ctx->Current.Attrib[mesaAttr]; stride = 0; } + assert(ptr); + assert(bytes); + + vbuffer[attr].buffer = + pipe_user_buffer_create(pipe->screen, ptr, bytes, + PIPE_BIND_VERTEX_BUFFER); + vbuffer[attr].buffer_offset = 0; /* Track user vertex buffers. */ @@ -438,13 +447,12 @@ setup_non_interleaved_attribs(struct gl_context *ctx, vbuffer[attr].stride = stride; /* in bytes */ velements[attr].src_offset = 0; - velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; + velements[attr].instance_divisor = array->InstanceDivisor; velements[attr].vertex_buffer_index = attr; - velements[attr].src_format - = st_pipe_vertex_format(arrays[mesaAttr]->Type, - arrays[mesaAttr]->Size, - arrays[mesaAttr]->Format, - arrays[mesaAttr]->Normalized); + velements[attr].src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized); assert(velements[attr].src_format); } } @@ -594,7 +602,8 @@ st_validate_varrays(struct gl_context *ctx, } else { setup_non_interleaved_attribs(ctx, vp, vpv, arrays, - vbuffer, velements, max_index, num_instances); + vbuffer, velements, max_index, + num_instances); num_vbuffers = vpv->num_inputs; num_velements = vpv->num_inputs; } @@ -647,7 +656,8 @@ st_draw_vbo(struct gl_context *ctx, for (i = 0; i < nr_prims; i++) { num_instances = MAX2(num_instances, prims[i].num_instances); } - } else { + } + else { /* Get min/max index for non-indexed drawing. */ min_index = ~0; max_index = 0; @@ -699,7 +709,8 @@ st_draw_vbo(struct gl_context *ctx, pipe->redefine_user_buffer(pipe, st->user_vb[i], min_index * stride, (max_index + 1 - min_index) * stride); - } else { + } + else { /* stride == 0 */ pipe->redefine_user_buffer(pipe, st->user_vb[i], 0, st->user_vb[i]->width0); @@ -743,7 +754,8 @@ st_draw_vbo(struct gl_context *ctx, } -void st_init_draw( struct st_context *st ) +void +st_init_draw(struct st_context *st) { struct gl_context *ctx = st->ctx; @@ -763,11 +775,10 @@ void st_init_draw( struct st_context *st ) } -void st_destroy_draw( struct st_context *st ) +void +st_destroy_draw(struct st_context *st) { #if FEATURE_feedback || FEATURE_rastpos draw_destroy(st->draw); #endif } - - -- cgit v1.2.3