X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_fbo.c;h=953295c0e1652331264302b630624e8834ac0fcb;hb=239792fb221556fbc0da6c046541ea078b6944db;hp=7ffee901cdb8fef9cc16af258a616f066240cdfb;hpb=25f26997670302b07d48207b28f385f85f6af9bb;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 7ffee901cdb..953295c0e16 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -47,6 +47,7 @@ #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" @@ -74,11 +75,18 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, 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; @@ -89,7 +97,6 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, 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 */ @@ -98,10 +105,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, 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); @@ -114,7 +118,11 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, */ 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. */ @@ -130,7 +138,12 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, 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); } @@ -140,7 +153,6 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, 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, @@ -167,29 +179,11 @@ st_renderbuffer_delete(struct gl_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() */ @@ -209,11 +203,10 @@ st_new_renderbuffer(struct gl_context *ctx, GLuint name) { 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; @@ -240,8 +233,6 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) 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) { @@ -262,17 +253,18 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) 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; @@ -286,9 +278,16 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) 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; } @@ -296,7 +295,6 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) /* 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; @@ -305,8 +303,6 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) } - - /** * Called via ctx->Driver.BindFramebufferEXT(). */ @@ -314,20 +310,7 @@ 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); + /* no-op */ } @@ -343,20 +326,26 @@ st_render_texture(struct gl_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 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; @@ -381,22 +370,18 @@ st_render_texture(struct gl_context *ctx, 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 = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(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; @@ -405,15 +390,7 @@ st_render_texture(struct gl_context *ctx, 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. @@ -438,10 +415,6 @@ st_finish_render_texture(struct gl_context *ctx, strb->rtt = NULL; - /* - printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface); - */ - /* restore previous framebuffer state */ st_invalidate_state(ctx, _NEW_BUFFERS); } @@ -471,13 +444,12 @@ st_validate_attachment(struct gl_context *ctx, return GL_FALSE; format = stObj->pt->format; - texFormat = - stObj->base.Image[att->CubeMapFace][att->TextureLevel]->TexFormat; + 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->Const.sRGBCapable && + 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); @@ -633,33 +605,120 @@ st_ReadBuffer(struct gl_context *ctx, GLenum buffer) } + +/** + * 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; -}