diff options
Diffstat (limited to 'src/mesa/state_tracker')
21 files changed, 1195 insertions, 207 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 7806df4a531..cf391f1f91f 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -34,8 +34,7 @@ #include "st_atom.h" #include "st_cb_bitmap.h" #include "st_program.h" - -#include "pipe/p_context.h" +#include "st_manager.h" /** @@ -136,9 +135,7 @@ void st_validate_state( struct st_context *st ) check_program_state( st ); - if (st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer(st->pipe->screen, - st->pipe->priv); + st_manager_validate_framebuffers(st); if (state->st == 0) return; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index fba7bfe2cea..79ad70909a9 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -38,7 +38,6 @@ #include "st_texture.h" #include "pipe/p_context.h" #include "cso_cache/cso_context.h" -#include "util/u_rect.h" #include "util/u_math.h" #include "util/u_inlines.h" @@ -164,17 +163,10 @@ update_framebuffer_state( struct st_context *st ) (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front); (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back); - if (st->pipe->surface_copy) { - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); - } else { - util_surface_copy(st->pipe, FALSE, - surf_front, 0, 0, - surf_back, 0, 0, - fb->Width, fb->Height); - } + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); } /* we're assuming we'll really draw to the front buffer */ st->frontbuffer_status = FRONT_STATUS_DIRTY; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index b446b2079cf..03e33361448 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -256,6 +256,8 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key) /* create the colormap/texture now if not already done */ if (!st->pixel_xfer.pixelmap_texture) { st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx); + st->pixel_xfer.pixelmap_sampler_view = st_sampler_view_from_texture(ctx->st->pipe, + st->pixel_xfer.pixelmap_texture); } /* with a little effort, we can do four pixel map look-ups with diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 57b71c1e7b0..241c001f94f 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -56,7 +56,7 @@ update_textures(struct st_context *st) /* loop over sampler units (aka tex image units) */ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_texture *pt = NULL; + struct pipe_sampler_view *sampler_view = NULL; if (samplersUsed & (1 << su)) { struct gl_texture_object *texObj; @@ -84,7 +84,7 @@ update_textures(struct st_context *st) st->state.num_textures = su + 1; - pt = st_get_stobj_texture(stObj); + sampler_view = st_get_stobj_sampler_view(stObj); } /* @@ -96,17 +96,17 @@ update_textures(struct st_context *st) } */ - pipe_texture_reference(&st->state.sampler_texture[su], pt); + pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); } - cso_set_sampler_textures(st->cso_context, - st->state.num_textures, - st->state.sampler_texture); + cso_set_fragment_sampler_views(st->cso_context, + st->state.num_textures, + st->state.sampler_views); if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { - cso_set_vertex_sampler_textures(st->cso_context, - MIN2(st->state.num_textures, - st->ctx->Const.MaxVertexTextureImageUnits), - st->state.sampler_texture); + cso_set_vertex_sampler_views(st->cso_context, + MIN2(st->state.num_textures, + st->ctx->Const.MaxVertexTextureImageUnits), + st->state.sampler_views); } } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index dfd8925edf4..9a0446bb710 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -397,7 +397,7 @@ setup_bitmap_vertex_data(struct st_context *st, static void draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, - struct pipe_texture *pt, + struct pipe_sampler_view *sv, const GLfloat *color) { struct st_context *st = ctx->st; @@ -435,7 +435,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_samplers(cso); - cso_save_sampler_textures(cso); + cso_save_fragment_sampler_views(cso); cso_save_viewport(cso); cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); @@ -465,11 +465,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* user textures, plus the bitmap texture */ { - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); - memcpy(textures, st->state.sampler_texture, sizeof(textures)); - textures[stfp->bitmap_sampler] = pt; - cso_set_sampler_textures(cso, num, textures); + memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); + sampler_views[stfp->bitmap_sampler] = sv; + cso_set_fragment_sampler_views(cso, num, sampler_views); } /* viewport state: viewport matching window dims */ @@ -507,7 +507,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* restore state */ cso_restore_rasterizer(cso); cso_restore_samplers(cso); - cso_restore_sampler_textures(cso); + cso_restore_fragment_sampler_views(cso); cso_restore_viewport(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); @@ -598,6 +598,7 @@ st_flush_bitmap_cache(struct st_context *st) if (st->ctx->DrawBuffer) { struct pipe_context *pipe = st->pipe; + struct pipe_sampler_view *sv; assert(cache->xmin <= cache->xmax); @@ -620,13 +621,18 @@ st_flush_bitmap_cache(struct st_context *st) cache->trans = NULL; } - draw_bitmap_quad(st->ctx, - cache->xpos, - cache->ypos, - cache->zpos, - BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - cache->texture, - cache->color); + sv = st_sampler_view_from_texture(st->pipe, cache->texture); + if (sv) { + draw_bitmap_quad(st->ctx, + cache->xpos, + cache->ypos, + cache->zpos, + BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, + sv, + cache->color); + + pipe_sampler_view_reference(&sv, NULL); + } } /* release/free the texture */ @@ -749,10 +755,18 @@ st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { + struct pipe_sampler_view *sv = st_sampler_view_from_texture(st->pipe, pt); + assert(pt->target == PIPE_TEXTURE_2D); - draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, pt, - st->ctx->Current.RasterColor); + + if (sv) { + draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], + width, height, sv, + st->ctx->Current.RasterColor); + + pipe_sampler_view_reference(&sv, NULL); + } + /* release/free the texture */ pipe_texture_reference(&pt, NULL); } diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 36e03018d9f..06b0a18fd22 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -69,6 +69,7 @@ st_BlitFramebuffer(GLcontext *ctx, const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); struct st_context *st = ctx->st; + struct pipe_context *pipe = st->pipe; const uint pFilter = ((filter == GL_NEAREST) ? PIPE_TEX_MIPFILTER_NEAREST : PIPE_TEX_MIPFILTER_LINEAR); @@ -111,8 +112,8 @@ st_BlitFramebuffer(GLcontext *ctx, &readFB->Attachment[readFB->_ColorReadBufferIndex]; if(srcAtt->Type == GL_TEXTURE) { - struct pipe_screen *screen = ctx->st->pipe->screen; - const struct st_texture_object *srcObj = + struct pipe_screen *screen = pipe->screen; + struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture); struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); @@ -132,7 +133,8 @@ st_BlitFramebuffer(GLcontext *ctx, return; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, st_get_stobj_sampler_view(srcObj), + srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); @@ -144,10 +146,11 @@ st_BlitFramebuffer(GLcontext *ctx, struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); struct pipe_surface *srcSurf = srcRb->surface; + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcRb, pipe); struct pipe_surface *dstSurf = dstRb->surface; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -179,11 +182,13 @@ st_BlitFramebuffer(GLcontext *ctx, if ((mask & depthStencil) == depthStencil && srcDepthSurf == srcStencilSurf && dstDepthSurf == dstStencilSurf) { + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcDepthRb, pipe); + /* Blitting depth and stencil values between combined * depth/stencil buffers. This is the ideal case for such buffers. */ util_blit_pixels(st->blit, - srcDepthSurf, srcX0, srcY0, srcX1, srcY1, + srcDepthSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstDepthSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index de86062fc40..6007c767182 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -47,16 +47,19 @@ #include "st_inlines.h" #include "pipe/p_context.h" -#include "util/u_inlines.h" #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "util/u_format.h" +#include "util/u_inlines.h" #include "util/u_simple_shaders.h" #include "util/u_draw_quad.h" #include "cso_cache/cso_context.h" +/** + * Do per-context initialization for glClear. + */ void st_init_clear(struct st_context *st) { @@ -67,8 +70,7 @@ st_init_clear(struct st_context *st) st->clear.raster.gl_rasterization_rules = 1; /* fragment shader state: color pass-through program */ - st->clear.fs = - util_make_fragment_passthrough_shader(pipe); + st->clear.fs = util_make_fragment_passthrough_shader(pipe); /* vertex shader state: color/position pass-through */ { @@ -82,6 +84,9 @@ st_init_clear(struct st_context *st) } +/** + * Free per-context state for glClear. + */ void st_destroy_clear(struct st_context *st) { @@ -131,7 +136,8 @@ draw_quad(GLcontext *ctx, } if (!st->clear.vbuf) { - st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, + st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, + PIPE_BUFFER_USAGE_VERTEX, max_slots * sizeof(st->clear.vertices)); } @@ -160,7 +166,8 @@ draw_quad(GLcontext *ctx, /* put vertex data into vbuf */ st_no_flush_pipe_buffer_write_nooverlap(st, st->clear.vbuf, - st->clear.vbuf_slot * sizeof(st->clear.vertices), + st->clear.vbuf_slot + * sizeof(st->clear.vertices), sizeof(st->clear.vertices), st->clear.vertices); @@ -289,7 +296,8 @@ clear_with_quad(GLcontext *ctx, cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); + draw_quad(ctx, x0, y0, x1, y1, + (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); @@ -301,7 +309,6 @@ clear_with_quad(GLcontext *ctx, cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); - } @@ -316,18 +323,22 @@ check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) ctx->Scissor.Y != 0 || ctx->Scissor.Width < rb->Width || ctx->Scissor.Height < rb->Height)) - return TRUE; + return GL_TRUE; if (!ctx->Color.ColorMask[0][0] || !ctx->Color.ColorMask[0][1] || !ctx->Color.ColorMask[0][2] || !ctx->Color.ColorMask[0][3]) - return TRUE; + return GL_TRUE; - return FALSE; + return GL_FALSE; } +/** + * Determine if we need to clear the combiend depth/stencil buffer by + * drawing a quad. + */ static INLINE GLboolean check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { @@ -344,12 +355,12 @@ check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) ctx->Scissor.Y != 0 || ctx->Scissor.Width < rb->Width || ctx->Scissor.Height < rb->Height)) - return TRUE; + return GL_TRUE; if (maskStencil) - return TRUE; + return GL_TRUE; - return FALSE; + return GL_FALSE; } @@ -367,13 +378,12 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) ctx->Scissor.Y != 0 || ctx->Scissor.Width < rb->Width || ctx->Scissor.Height < rb->Height)) - return TRUE; + return GL_TRUE; - if (isDS && - ctx->DrawBuffer->Visual.stencilBits > 0) - return TRUE; + if (isDS && ctx->DrawBuffer->Visual.stencilBits > 0) + return GL_TRUE; - return FALSE; + return GL_FALSE; } @@ -394,30 +404,33 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) rb->Format == MESA_FORMAT_S8_Z24); if (maskStencil) - return TRUE; + return GL_TRUE; if (ctx->Scissor.Enabled && (ctx->Scissor.X != 0 || ctx->Scissor.Y != 0 || ctx->Scissor.Width < rb->Width || ctx->Scissor.Height < rb->Height)) - return TRUE; + return GL_TRUE; /* This is correct, but it is necessary to look at the depth clear * value held in the surface when it comes time to issue the clear, * rather than taking depth and stencil clear values from the * current state. */ - if (isDS && - ctx->DrawBuffer->Visual.depthBits > 0) - return TRUE; + if (isDS && ctx->DrawBuffer->Visual.depthBits > 0) + return GL_TRUE; - return FALSE; + return GL_FALSE; } -void st_flush_clear( struct st_context *st ) +/** + * Called when we need to flush. + */ +void +st_flush_clear(struct st_context *st) { /* Release vertex buffer to avoid synchronous rendering if we were * to map it in the next frame. @@ -430,10 +443,9 @@ void st_flush_clear( struct st_context *st ) /** * Called via ctx->Driver.Clear() - * XXX: doesn't pick up the differences between front/back/left/right - * clears. Need to sort that out... */ -static void st_clear(GLcontext *ctx, GLbitfield mask) +static void +st_Clear(GLcontext *ctx, GLbitfield mask) { static const GLbitfield BUFFER_BITS_DS = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); @@ -442,8 +454,8 @@ static void st_clear(GLcontext *ctx, GLbitfield mask) = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *stencilRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; - GLbitfield quad_buffers = 0; - GLbitfield clear_buffers = 0; + GLbitfield quad_buffers = 0x0; + GLbitfield clear_buffers = 0x0; GLuint i; /* This makes sure the pipe has the latest scissor, etc values */ @@ -528,7 +540,8 @@ static void st_clear(GLcontext *ctx, GLbitfield mask) } -void st_init_clear_functions(struct dd_function_table *functions) +void +st_init_clear_functions(struct dd_function_table *functions) { - functions->Clear = st_clear; + functions->Clear = st_Clear; } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index c44d0fc3e86..c9d1e9c6c4b 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -59,7 +59,6 @@ #include "util/u_draw_quad.h" #include "util/u_format.h" #include "util/u_math.h" -#include "util/u_rect.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -525,7 +524,7 @@ static void draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, GLfloat zoomX, GLfloat zoomY, - struct pipe_texture *pt, + struct pipe_sampler_view *sv, void *driver_vp, void *driver_fp, const GLfloat *color, @@ -548,7 +547,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_viewport(cso); cso_save_samplers(cso); - cso_save_sampler_textures(cso); + cso_save_fragment_sampler_views(cso); cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); @@ -608,13 +607,13 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* texture state: */ if (st->pixel_xfer.pixelmap_enabled) { - struct pipe_texture *textures[2]; - textures[0] = pt; - textures[1] = st->pixel_xfer.pixelmap_texture; - pipe->set_fragment_sampler_textures(pipe, 2, textures); + struct pipe_sampler_view *sampler_views[2]; + sampler_views[0] = sv; + sampler_views[1] = st->pixel_xfer.pixelmap_sampler_view; + cso_set_fragment_sampler_views(cso, 2, sampler_views); } else { - pipe->set_fragment_sampler_textures(pipe, 1, &pt); + cso_set_fragment_sampler_views(cso, 1, &sv); } /* Compute Gallium window coords (y=0=top) with pixel zoom. @@ -635,14 +634,14 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, z = z * 2.0 - 1.0; draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, - (GLfloat) width / pt->width0, - (GLfloat) height / pt->height0); + (GLfloat) width / sv->texture->width0, + (GLfloat) height / sv->texture->height0); /* restore state */ cso_restore_rasterizer(cso); cso_restore_viewport(cso); cso_restore_samplers(cso); - cso_restore_sampler_textures(cso); + cso_restore_fragment_sampler_views(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); @@ -835,12 +834,17 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, struct pipe_texture *pt = make_texture(st, width, height, format, type, unpack, pixels); if (pt) { - draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, - driver_vp, - driver_fp, - color, GL_FALSE); + struct pipe_sampler_view *sv = st_sampler_view_from_texture(st->pipe, pt); + + if (sv) { + draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], + width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, + sv, + driver_vp, + driver_fp, + color, GL_FALSE); + pipe_sampler_view_reference(&sv, NULL); + } pipe_texture_reference(&pt, NULL); } } @@ -959,42 +963,17 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct st_renderbuffer *rbRead; void *driver_vp, *driver_fp; struct pipe_texture *pt; + struct pipe_sampler_view *sv; GLfloat *color; enum pipe_format srcFormat, texFormat; GLboolean invertTex = GL_FALSE; + GLint readX, readY, readW, readH; + struct gl_pixelstore_attrib pack = ctx->DefaultPacking; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); st_validate_state(st); - if (srcx < 0) { - width -= -srcx; - dstx += -srcx; - srcx = 0; - } - - if (srcy < 0) { - height -= -srcy; - dsty += -srcy; - srcy = 0; - } - - if (dstx < 0) { - width -= -dstx; - srcx += -dstx; - dstx = 0; - } - - if (dsty < 0) { - height -= -dsty; - srcy += -dsty; - dsty = 0; - } - - if (width < 0 || height < 0) - return; - - if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); @@ -1027,7 +1006,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL); - assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ + assert(texFormat != PIPE_FORMAT_NONE); } else { /* default color format */ @@ -1037,27 +1016,38 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, } } + /* Invert src region if needed */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcy = ctx->ReadBuffer->Height - srcy - height; - - if (srcy < 0) { - height -= -srcy; - srcy = 0; - } - - if (height < 0) - return; - invertTex = !invertTex; } + /* Clip the read region against the src buffer bounds. + * We'll still allocate a temporary buffer/texture for the original + * src region size but we'll only read the region which is on-screen. + * This may mean that we draw garbage pixels into the dest region, but + * that's expected. + */ + readX = srcx; + readY = srcy; + readW = width; + readH = height; + _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); + readW = MAX2(0, readW); + readH = MAX2(0, readH); + /* alloc temporary texture */ pt = alloc_texture(st, width, height, texFormat); if (!pt) return; + sv = st_sampler_view_from_texture(st->pipe, pt); + if (!sv) { + pipe_texture_reference(&pt, NULL); + return; + } + /* Make temporary texture which is a copy of the src region. - * We'll draw a quad with this texture to draw the dest image. */ if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ @@ -1066,19 +1056,12 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, PIPE_BUFFER_USAGE_GPU_READ); struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - psTex, /* dest */ - 0, 0, /* destx/y */ - psRead, - srcx, srcy, width, height); - } else { - util_surface_copy(pipe, FALSE, - psTex, - 0, 0, - psRead, - srcx, srcy, width, height); - } + + pipe->surface_copy(pipe, + psTex, /* dest surf */ + pack.SkipPixels, pack.SkipRows, /* dest pos */ + psRead, /* src surf */ + readX, readY, readW, readH); /* src region */ if (0) { /* debug */ @@ -1093,8 +1076,8 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, srcx, srcy, width, - height); + PIPE_TRANSFER_READ, + readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; @@ -1109,20 +1092,21 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 0, 0, width, height); + /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - pipe_get_tile_rgba(pipe, ptRead, 0, 0, width, height, buf); - pipe_put_tile_rgba(pipe, ptTex, 0, 0, width, height, buf); - + pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, ptRead, 0, 0, width, height, buf); - pipe_put_tile_z(pipe, ptTex, 0, 0, width, height, buf); + pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, buf); free(buf); } @@ -1130,15 +1114,18 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, pipe->tex_transfer_destroy(pipe, ptTex); } - /* draw textured quad */ + /* OK, the texture 'pt' contains the src image/pixels. Now draw a + * textured quad with that texture. + */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, + sv, driver_vp, driver_fp, color, invertTex); pipe_texture_reference(&pt, NULL); + pipe_sampler_view_reference(&sv, NULL); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index abf0c8d6cb1..84c2474038d 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -48,9 +48,9 @@ #include "st_format.h" #include "st_public.h" #include "st_texture.h" +#include "st_manager.h" #include "util/u_format.h" -#include "util/u_rect.h" #include "util/u_inlines.h" @@ -103,6 +103,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, */ pipe_surface_reference( &strb->surface, NULL ); pipe_texture_reference( &strb->texture, NULL ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); /* Setup new texture template. */ @@ -162,6 +163,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) ASSERT(strb); pipe_surface_reference(&strb->surface, NULL); pipe_texture_reference(&strb->texture, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); free(strb->data); free(strb); } @@ -368,6 +370,8 @@ st_render_texture(GLcontext *ctx, pipe_surface_reference(&strb->surface, NULL); + pipe_sampler_view_reference(&strb->sampler_view, st_get_stobj_sampler_view(stObj)); + assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ @@ -513,17 +517,10 @@ copy_back_to_front(struct st_context *st, (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back); if (surf_front && surf_back) { - if (st->pipe->surface_copy) { - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); - } else { - util_surface_copy(st->pipe, FALSE, - surf_front, 0, 0, - surf_back, 0, 0, - fb->Width, fb->Height); - } + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); } } @@ -614,8 +611,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb) static void st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) { + GLframebuffer *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(ctx->st, fb, idx); + } + check_create_front_buffers(ctx, ctx->DrawBuffer); } @@ -626,8 +633,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) static void st_ReadBuffer(GLcontext *ctx, GLenum buffer) { + GLframebuffer *fb = ctx->ReadBuffer; + (void) buffer; - check_create_front_buffers(ctx, ctx->ReadBuffer); + + /* add the renderbuffer on demand */ + st_manager_add_color_renderbuffer(ctx->st, fb, fb->_ColorReadBufferIndex); + check_create_front_buffers(ctx, fb); } @@ -647,3 +659,14 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->DrawBuffers = st_DrawBuffers; functions->ReadBuffer = st_ReadBuffer; } + +struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe) +{ + if (!rb->sampler_view) { + rb->sampler_view = st_sampler_view_from_texture(pipe, rb->texture); + } + + return rb->sampler_view; +} diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index bea6eb89c3e..7a45a608fe1 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -39,6 +39,7 @@ struct st_renderbuffer struct gl_renderbuffer Base; struct pipe_texture *texture; struct pipe_surface *surface; /* temporary view into texture */ + struct pipe_sampler_view *sampler_view; enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ GLboolean defined; /**< defined contents? */ @@ -55,6 +56,7 @@ struct st_renderbuffer /** Render to texture state */ struct pipe_texture *texture_save; struct pipe_surface *surface_save; + struct pipe_sampler_view *sampler_view_save; }; @@ -71,5 +73,9 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); extern void st_init_fbo_functions(struct dd_function_table *functions); +extern struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe); + #endif /* ST_CB_FBO_H */ diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 28a384ba49b..30e7afcf2a3 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -40,6 +40,7 @@ #include "st_cb_clear.h" #include "st_cb_fbo.h" #include "st_public.h" +#include "st_manager.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -74,12 +75,9 @@ display_front_buffer(struct st_context *st) = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); if (strb) { - struct pipe_surface *front_surf = strb->surface; - /* Hook for copying "fake" frontbuffer if necessary: */ - st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf, - st->winsys_drawable_handle ); + st_manager_flush_frontbuffer(st); /* st->frontbuffer_status = FRONT_STATUS_UNDEFINED; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 080a5f9bfb8..7afb275fe2f 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -45,6 +45,7 @@ #include "st_debug.h" #include "st_context.h" +#include "st_atom.h" #include "st_cb_readpixels.h" #include "st_cb_fbo.h" #include "st_public.h" @@ -350,6 +351,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* XXX convolution not done yet */ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); + st_validate_state(ctx->st); + /* Do all needed clipping here, so that we can forget about it later */ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { /* The ReadPixels transfer is totally outside the window bounds */ diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 626e6ad660d..390ada5489c 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -63,6 +63,7 @@ #include "util/u_blit.h" #include "util/u_format.h" #include "util/u_surface.h" +#include "util/u_sampler.h" #include "util/u_math.h" @@ -123,7 +124,17 @@ st_DeleteTextureObject(GLcontext *ctx, struct st_texture_object *stObj = st_texture_object(texObj); if (stObj->pt) pipe_texture_reference(&stObj->pt, NULL); - + if (stObj->sampler_view) { + if (stObj->sampler_view->context != ctx->st->pipe) { + /* Take "ownership" of this texture sampler view by setting + * its context pointer to this context. This avoids potential + * crashes when the texture object is shared among contexts + * and the original/owner context has already been destroyed. + */ + stObj->sampler_view->context = ctx->st->pipe; + } + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + } _mesa_delete_texture_object(ctx, texObj); } @@ -312,6 +323,8 @@ guess_and_alloc_texture(struct st_context *st, depth, usage); + stObj->pipe = st->pipe; + DBG("%s - success\n", __FUNCTION__); } @@ -376,6 +389,8 @@ compress_with_blit(GLcontext * ctx, gl_format mesa_format; struct pipe_texture templ; struct pipe_texture *src_tex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; struct pipe_surface *dst_surface; struct pipe_transfer *tex_xfer; void *map; @@ -437,9 +452,16 @@ compress_with_blit(GLcontext * ctx, pipe->transfer_unmap(pipe, tex_xfer); pipe->tex_transfer_destroy(pipe, tex_xfer); + /* Create temporary sampler view */ + u_sampler_view_default_template(&view_templ, + src_tex, + src_tex->format); + src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); + + /* copy / compress image */ util_blit_pixels_tex(ctx->st->blit, - src_tex, /* pipe_texture (src) */ + src_view, /* sampler view (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -451,6 +473,7 @@ compress_with_blit(GLcontext * ctx, pipe_surface_reference(&dst_surface, NULL); pipe_texture_reference(&src_tex, NULL); + pipe_sampler_view_reference(&src_view, NULL); return GL_TRUE; } @@ -556,6 +579,7 @@ st_TexImage(GLcontext * ctx, DBG("release it\n"); pipe_texture_reference(&stObj->pt, NULL); assert(!stObj->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); stObj->teximage_realloc = FALSE; } } @@ -813,6 +837,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_sampler_view *src_view = st_get_stobj_sampler_view(stObj); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; @@ -829,7 +855,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, /* blit/render/decompress */ util_blit_pixels_tex(ctx->st->blit, - stImage->pt, /* pipe_texture (src) */ + src_view, /* pipe_texture (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -882,6 +908,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, _mesa_unmap_pbo_dest(ctx, &ctx->Pack); + pipe->tex_transfer_destroy(pipe, tex_xfer); + /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); } @@ -906,7 +934,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, GLubyte *dest; if (stImage->pt && - util_format_is_compressed(stImage->pt->format) && + util_format_is_s3tc(stImage->pt->format) && !compressed_dst) { /* Need to decompress the texture. * We'll do this by rendering a textured quad. @@ -1540,8 +1568,7 @@ st_copy_texsubimage(GLcontext *ctx, if (ctx->_ImageTransferState == 0x0) { - if (pipe->surface_copy && - matching_base_formats && + if (matching_base_formats && src_format == dest_format && !do_flip) { @@ -1593,6 +1620,7 @@ st_copy_texsubimage(GLcontext *ctx, } util_blit_pixels_writemask(ctx->st->blit, strb->surface, + st_renderbuffer_get_sampler_view(strb, pipe), srcX, srcY0, srcX + width, srcY1, dest_surface, @@ -1789,6 +1817,7 @@ st_finalize_texture(GLcontext *ctx, firstImage->pt != stObj->pt && firstImage->pt->last_level >= stObj->lastLevel) { pipe_texture_reference(&stObj->pt, firstImage->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); } /* bytes per pixel block (blocks are usually 1x1) */ @@ -1808,6 +1837,7 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->depth0 != firstImage->base.Depth2) { pipe_texture_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; } } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index ca6d4dfb069..72f5a9c1e0b 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -30,9 +30,9 @@ #include "vbo/vbo.h" #include "shader/shader_api.h" #include "glapi/glapi.h" +#include "st_context.h" #include "st_public.h" #include "st_debug.h" -#include "st_context.h" #include "st_cb_accum.h" #include "st_cb_bitmap.h" #include "st_cb_blit.h" @@ -63,6 +63,7 @@ #include "st_program.h" #include "pipe/p_context.h" #include "util/u_inlines.h" +#include "util/u_rect.h" #include "draw/draw_context.h" #include "cso_cache/cso_context.h" @@ -97,6 +98,19 @@ st_get_msaa(void) } +/** Default method for pipe_context::surface_copy() */ +static void +st_surface_copy(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned dst_x, unsigned dst_y, + struct pipe_surface *src, + unsigned src_x, unsigned src_y, + unsigned w, unsigned h) +{ + util_surface_copy(pipe, FALSE, dst, dst_x, dst_y, src, src_x, src_y, w, h); +} + + static struct st_context * st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) { @@ -166,6 +180,10 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) st_init_limits(st); st_init_extensions(st); + /* plug in helper driver functions if needed */ + if (!pipe->surface_copy) + pipe->surface_copy = st_surface_copy; + return st; } @@ -215,8 +233,8 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawtex(st); #endif - for (i = 0; i < Elements(st->state.sampler_texture); i++) { - pipe_texture_reference(&st->state.sampler_texture[i], NULL); + for (i = 0; i < Elements(st->state.sampler_views); i++) { + pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } for (i = 0; i < Elements(st->state.constants); i++) { diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index e2d34fb3d10..786beaec08b 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -31,6 +31,7 @@ #include "main/mtypes.h" #include "shader/prog_cache.h" #include "pipe/p_state.h" +#include "state_tracker/st_api.h" struct st_context; @@ -73,6 +74,8 @@ struct st_tracked_state { struct st_context { + struct st_context_iface iface; + GLcontext *ctx; struct pipe_context *pipe; @@ -94,7 +97,7 @@ struct st_context struct pipe_clip_state clip; struct pipe_buffer *constants[2]; struct pipe_framebuffer_state framebuffer; - struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_scissor_state scissor; struct pipe_viewport_state viewport; @@ -141,6 +144,7 @@ struct st_context struct st_fragment_program *combined_prog; GLuint combined_prog_sn; struct pipe_texture *pixelmap_texture; + struct pipe_sampler_view *pixelmap_sampler_view; boolean pixelmap_enabled; /**< use the pixelmap texture? */ } pixel_xfer; @@ -206,6 +210,11 @@ struct st_framebuffer GLframebuffer Base; void *Private; GLuint InitWidth, InitHeight; + + struct st_framebuffer_iface *iface; + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned num_statts; + int32_t revalidate; }; diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index 0a91183f89d..d3c43bbc68a 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -197,6 +197,7 @@ st_set_framebuffer_surface(struct st_framebuffer *stfb, /* replace the renderbuffer's surface/texture pointers */ pipe_surface_reference( &strb->surface, surf ); pipe_texture_reference( &strb->texture, surf->texture ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); if (ctx) { /* If ctx isn't set, we've likely not made current yet. diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index b2521433c87..030b0a0f065 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -79,22 +79,23 @@ st_destroy_generate_mipmap(struct st_context *st) static boolean st_render_mipmap(struct st_context *st, GLenum target, - struct pipe_texture *pt, + struct st_texture_object *stObj, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; + struct pipe_sampler_view *psv = st_get_stobj_sampler_view(stObj); const uint face = _mesa_tex_target_to_face(target); assert(target != GL_TEXTURE_3D); /* not done yet */ /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, pt->target, + if (!screen->is_format_supported(screen, psv->format, psv->texture->target, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { return FALSE; } - util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, + util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, PIPE_TEX_FILTER_LINEAR); return TRUE; @@ -211,6 +212,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = ctx->st; + struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel; @@ -229,7 +231,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. */ - struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_texture *oldTex = stObj->pt; GLboolean needFlush; @@ -255,6 +256,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_texture_reference(&oldTex, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); pt = stObj->pt; } @@ -264,7 +266,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* Recall that the Mesa BaseLevel image is stored in the gallium * texture's level[0] position. So pass baseLevel=0 here. */ - if (!st_render_mipmap(st, target, pt, 0, lastLevel)) { + if (!st_render_mipmap(st, target, stObj, 0, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c new file mode 100644 index 00000000000..cac62e4a14c --- /dev/null +++ b/src/mesa/state_tracker/st_manager.c @@ -0,0 +1,802 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_pointer.h" +#include "util/u_inlines.h" +#include "util/u_atomic.h" + +#include "main/mtypes.h" +#include "main/context.h" +#include "main/texobj.h" +#include "main/teximage.h" +#include "main/texstate.h" +#include "main/texfetch.h" +#include "main/framebuffer.h" +#include "main/renderbuffer.h" +#include "st_texture.h" + +#include "st_context.h" +#include "st_format.h" +#include "st_cb_fbo.h" +#include "st_manager.h" + +/* these functions are defined in st_context.c */ +struct st_context * +st_create_context(struct pipe_context *pipe, + const __GLcontextModes *visual, + struct st_context *share); +void st_destroy_context(struct st_context *st); +void st_flush(struct st_context *st, uint pipeFlushFlags, + struct pipe_fence_handle **fence); + +/** + * Cast wrapper to convert a GLframebuffer to an st_framebuffer. + * Return NULL if the GLframebuffer is a user-created framebuffer. + * We'll only return non-null for window system framebuffers. + * Note that this function may fail. + */ +static INLINE struct st_framebuffer * +st_ws_framebuffer(GLframebuffer *fb) +{ + /* FBO cannot be casted. See st_new_framebuffer */ + return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL); +} + +/** + * Map an attachment to a buffer index. + */ +static INLINE gl_buffer_index +attachment_to_buffer_index(enum st_attachment_type statt) +{ + gl_buffer_index index; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + index = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + index = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + index = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + index = BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + index = BUFFER_DEPTH; + break; + case ST_ATTACHMENT_ACCUM: + index = BUFFER_ACCUM; + break; + case ST_ATTACHMENT_SAMPLE: + default: + index = BUFFER_COUNT; + break; + } + + return index; +} + +/** + * Map a buffer index to an attachment. + */ +static INLINE enum st_attachment_type +buffer_index_to_attachment(gl_buffer_index index) +{ + enum st_attachment_type statt; + + switch (index) { + case BUFFER_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case BUFFER_FRONT_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + case BUFFER_BACK_RIGHT: + statt = ST_ATTACHMENT_BACK_RIGHT; + break; + case BUFFER_DEPTH: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + break; + case BUFFER_ACCUM: + statt = ST_ATTACHMENT_ACCUM; + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + return statt; +} + +/** + * Validate a framebuffer to make sure up-to-date pipe_textures are used. + */ +static void +st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) +{ + struct pipe_screen *screen = st->pipe->screen; + struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + uint width, height; + unsigned i; + boolean changed = FALSE; + + if (!p_atomic_read(&stfb->revalidate)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures)) + return; + + width = stfb->Base.Width; + height = stfb->Base.Height; + + for (i = 0; i < stfb->num_statts; i++) { + struct st_renderbuffer *strb; + struct pipe_surface *ps; + gl_buffer_index idx; + + if (!textures[i]) + continue; + + idx = attachment_to_buffer_index(stfb->statts[i]); + if (idx >= BUFFER_COUNT) { + pipe_texture_reference(&textures[i], NULL); + continue; + } + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + assert(strb); + if (strb->texture == textures[i]) { + pipe_texture_reference(&textures[i], NULL); + continue; + } + + ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + if (ps) { + pipe_surface_reference(&strb->surface, ps); + pipe_texture_reference(&strb->texture, ps->texture); + /* ownership transfered */ + pipe_surface_reference(&ps, NULL); + + changed = TRUE; + + strb->Base.Width = strb->surface->width; + strb->Base.Height = strb->surface->height; + + width = strb->Base.Width; + height = strb->Base.Height; + } + + pipe_texture_reference(&textures[i], NULL); + } + + if (changed) { + st->dirty.st |= ST_NEW_FRAMEBUFFER; + _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); + + assert(stfb->Base.Width == width); + assert(stfb->Base.Height == height); + } + + p_atomic_set(&stfb->revalidate, FALSE); +} + +/** + * Update the attachments to validate by looping the existing renderbuffers. + */ +static void +st_framebuffer_update_attachments(struct st_framebuffer *stfb) +{ + gl_buffer_index idx; + + stfb->num_statts = 0; + for (idx = 0; idx < BUFFER_COUNT; idx++) { + struct st_renderbuffer *strb; + enum st_attachment_type statt; + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + if (!strb || strb->software) + continue; + + statt = buffer_index_to_attachment(idx); + if (statt != ST_ATTACHMENT_INVALID && + st_visual_have_buffers(stfb->iface->visual, 1 << statt)) + stfb->statts[stfb->num_statts++] = statt; + } + + p_atomic_set(&stfb->revalidate, TRUE); +} + +/** + * Add a renderbuffer to the framebuffer. + */ +static boolean +st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, + gl_buffer_index idx) +{ + struct gl_renderbuffer *rb; + enum pipe_format format; + int samples; + boolean sw; + + /* do not distinguish depth/stencil buffers */ + if (idx == BUFFER_STENCIL) + idx = BUFFER_DEPTH; + + switch (idx) { + case BUFFER_DEPTH: + format = stfb->iface->visual->depth_stencil_format; + sw = FALSE; + break; + case BUFFER_ACCUM: + format = stfb->iface->visual->accum_format; + sw = TRUE; + break; + default: + format = stfb->iface->visual->color_format; + sw = FALSE; + break; + } + + if (format == PIPE_FORMAT_NONE) + return FALSE; + + samples = stfb->iface->visual->samples; + if (!samples) + samples = st_get_msaa(); + + rb = st_new_renderbuffer_fb(format, samples, sw); + if (!rb) + return FALSE; + + if (idx != BUFFER_DEPTH) { + _mesa_add_renderbuffer(&stfb->Base, idx, rb); + } + else { + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb); + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb); + } + + return TRUE; +} + +/** + * Intialize a __GLcontextModes from a visual. + */ +static void +st_visual_to_context_mode(const struct st_visual *visual, + __GLcontextModes *mode) +{ + memset(mode, 0, sizeof(*mode)); + + if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) + mode->doubleBufferMode = GL_TRUE; + if (st_visual_have_buffers(visual, + ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) + mode->stereoMode = GL_TRUE; + + if (visual->color_format != PIPE_FORMAT_NONE) { + mode->rgbMode = GL_TRUE; + + mode->redBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->greenBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->blueBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->alphaBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + + mode->rgbBits = mode->redBits + + mode->greenBits + mode->blueBits + mode->alphaBits; + } + + if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { + mode->depthBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 0); + mode->stencilBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 1); + + mode->haveDepthBuffer = mode->depthBits > 0; + mode->haveStencilBuffer = mode->stencilBits > 0; + } + + if (visual->accum_format != PIPE_FORMAT_NONE) { + mode->haveAccumBuffer = GL_TRUE; + + mode->accumRedBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->accumGreenBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->accumBlueBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->accumAlphaBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + } + + if (visual->samples) { + mode->sampleBuffers = 1; + mode->samples = visual->samples; + } +} + +/** + * Determine the default draw or read buffer from a visual. + */ +static void +st_visual_to_default_buffer(const struct st_visual *visual, + GLenum *buffer, GLint *index) +{ + enum st_attachment_type statt; + GLenum buf; + gl_buffer_index idx; + + statt = visual->render_buffer; + /* do nothing if an invalid render buffer is specified */ + if (statt == ST_ATTACHMENT_INVALID || + !st_visual_have_buffers(visual, 1 << statt)) + return; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + buf = GL_FRONT_LEFT; + idx = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buf = GL_BACK_LEFT; + idx = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + buf = GL_FRONT_RIGHT; + idx = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + buf = GL_BACK_RIGHT; + idx = BUFFER_BACK_RIGHT; + break; + default: + buf = GL_NONE; + idx = BUFFER_COUNT; + break; + } + + if (buf != GL_NONE) { + if (buffer) + *buffer = buf; + if (index) + *index = idx; + } +} + +/** + * Create a framebuffer from a manager interface. + */ +static struct st_framebuffer * +st_framebuffer_create(struct st_framebuffer_iface *stfbi) +{ + struct st_framebuffer *stfb; + __GLcontextModes mode; + gl_buffer_index idx; + + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return NULL; + + st_visual_to_context_mode(stfbi->visual, &mode); + _mesa_initialize_window_framebuffer(&stfb->Base, &mode); + + /* modify the draw/read buffers of the fb */ + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0], + &stfb->Base._ColorDrawBufferIndexes[0]); + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer, + &stfb->Base._ColorReadBufferIndex); + + stfb->iface = stfbi; + + /* add the color buffer */ + idx = stfb->Base._ColorDrawBufferIndexes[0]; + if (!st_framebuffer_add_renderbuffer(stfb, idx)) { + FREE(stfb); + return NULL; + } + + st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH); + st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM); + + st_framebuffer_update_attachments(stfb); + + stfb->Base.Initialized = GL_TRUE; + + return stfb; +} + +/** + * Reference a framebuffer. + */ +static void +st_framebuffer_reference(struct st_framebuffer **ptr, + struct st_framebuffer *stfb) +{ + GLframebuffer *fb = &stfb->Base; + _mesa_reference_framebuffer((GLframebuffer **) ptr, fb); +} + +static void +st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stfb; + + /* either draw or read winsys fb */ + stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer); + if (!stfb || stfb->iface != stfbi) + stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer); + assert(stfb && stfb->iface == stfbi); + + p_atomic_set(&stfb->revalidate, TRUE); +} + +static void +st_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct st_context *st = (struct st_context *) stctxi; + st_flush(st, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + st_manager_flush_frontbuffer(st); +} + +static boolean +st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_texture *tex, boolean mipmap) +{ + struct st_context *st = (struct st_context *) stctxi; + GLcontext *ctx = st->ctx; + struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + struct st_texture_object *stObj; + struct st_texture_image *stImage; + GLenum internalFormat; + + switch (target) { + case ST_TEXTURE_1D: + target = GL_TEXTURE_1D; + break; + case ST_TEXTURE_2D: + target = GL_TEXTURE_2D; + break; + case ST_TEXTURE_3D: + target = GL_TEXTURE_3D; + break; + case ST_TEXTURE_RECT: + target = GL_TEXTURE_RECTANGLE_ARB; + break; + default: + return FALSE; + break; + } + + if (util_format_get_component_bits(internal_format, + UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texObj = _mesa_select_tex_object(ctx, texUnit, target); + _mesa_lock_texture(ctx, texObj); + + stObj = st_texture_object(texObj); + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stImage = st_texture_image(texImage); + if (tex) { + _mesa_init_teximage_fields(ctx, target, texImage, + tex->width0, tex->height0, 1, 0, internalFormat); + texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_set_fetch_functions(texImage, 2); + } + else { + _mesa_clear_texture_image(ctx, texImage); + } + + stObj->pipe = st->pipe; + pipe_texture_reference(&stImage->pt, tex); + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_unlock_texture(ctx, texObj); + + return TRUE; +} + +static void +st_context_destroy(struct st_context_iface *stctxi) +{ + struct st_context *st = (struct st_context *) stctxi; + st_destroy_context(st); +} + +static struct st_context_iface * +st_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct st_context *shared_ctx = (struct st_context *) shared_stctxi; + struct st_context *st; + struct pipe_context *pipe; + __GLcontextModes mode; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + + st_visual_to_context_mode(visual, &mode); + st = st_create_context(pipe, &mode, shared_ctx); + if (!st) { + pipe->destroy(pipe); + return NULL; + } + + st->iface.destroy = st_context_destroy; + + st->iface.notify_invalid_framebuffer = + st_context_notify_invalid_framebuffer; + st->iface.flush = st_context_flush; + + st->iface.teximage = st_context_teximage; + st->iface.copy = NULL; + + st->iface.st_context_private = (void *) smapi; + + return &st->iface; +} + +static boolean +st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stdraw, *stread, *stfb; + boolean ret; + + _glapi_check_multithread(); + + if (st) { + /* reuse/create the draw fb */ + stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer); + if (stfb && stfb->iface == stdrawi) { + stdraw = NULL; + st_framebuffer_reference(&stdraw, stfb); + } + else { + stdraw = st_framebuffer_create(stdrawi); + } + + /* reuse/create the read fb */ + stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer); + if (!stfb || stfb->iface != streadi) + stfb = stdraw; + if (stfb && stfb->iface == streadi) { + stread = NULL; + st_framebuffer_reference(&stread, stfb); + } + else { + stread = st_framebuffer_create(streadi); + } + + if (stdraw && stread) { + st_framebuffer_validate(stdraw, st); + if (stread != stdraw) + st_framebuffer_validate(stread, st); + + /* modify the draw/read buffers of the context */ + st_visual_to_default_buffer(stdraw->iface->visual, + &st->ctx->Color.DrawBuffer[0], NULL); + st_visual_to_default_buffer(stread->iface->visual, + &st->ctx->Pixel.ReadBuffer, NULL); + + ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); + } + else { + ret = FALSE; + } + + st_framebuffer_reference(&stdraw, NULL); + st_framebuffer_reference(&stread, NULL); + } + else { + ret = _mesa_make_current(NULL, NULL, NULL); + } + + return ret; +} + +static struct st_context_iface * +st_api_get_current(struct st_api *stapi) +{ + GET_CURRENT_CONTEXT(ctx); + struct st_context *st = (ctx) ? ctx->st : NULL; + + return (st) ? &st->iface : NULL; +} + +static boolean +st_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + return TRUE; +} + +static st_proc_t +st_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + return (st_proc_t) _glapi_get_proc_address(procname); +} + +static void +st_api_destroy(struct st_api *stapi) +{ + FREE(stapi); +} + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +st_manager_flush_frontbuffer(struct st_context *st) +{ + struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); + struct st_renderbuffer *strb = NULL; + + if (stfb) + strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + if (!strb) + return; + + /* st_public.h */ + if (!stfb->iface) { + struct pipe_surface *front_surf = strb->surface; + st->pipe->screen->flush_frontbuffer(st->pipe->screen, + front_surf, st->winsys_drawable_handle); + return; + } + + stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT); +} + +/** + * Re-validate the framebuffers. + */ +void +st_manager_validate_framebuffers(struct st_context *st) +{ + struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); + struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); + + /* st_public.h */ + if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) { + struct pipe_screen *screen = st->pipe->screen; + if (screen->update_buffer) + screen->update_buffer(screen, st->pipe->priv); + return; + } + + if (stdraw) + st_framebuffer_validate(stdraw, st); + if (stread && stread != stdraw) + st_framebuffer_validate(stread, st); +} + +/** + * Add a color renderbuffer on demand. + */ +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx) +{ + struct st_framebuffer *stfb = st_ws_framebuffer(fb); + + /* FBO or st_public.h */ + if (!stfb || !stfb->iface) + return FALSE; + + if (stfb->Base.Attachment[idx].Renderbuffer) + return TRUE; + + switch (idx) { + case BUFFER_FRONT_LEFT: + case BUFFER_BACK_LEFT: + case BUFFER_FRONT_RIGHT: + case BUFFER_BACK_RIGHT: + break; + default: + return FALSE; + break; + } + + if (!st_framebuffer_add_renderbuffer(stfb, idx)) + return FALSE; + + st_framebuffer_update_attachments(stfb); + st_invalidate_state(st->ctx, _NEW_BUFFERS); + + return TRUE; +} + +/** + * Create an st_api to manage the state tracker. + */ +struct st_api * +st_manager_create_api(void) +{ + struct st_api *stapi; + + stapi = CALLOC_STRUCT(st_api); + if (stapi) { + stapi->destroy = st_api_destroy; + stapi->get_proc_address = st_api_get_proc_address; + stapi->is_visual_supported = st_api_is_visual_supported; + + stapi->create_context = st_api_create_context; + stapi->make_current = st_api_make_current; + stapi->get_current = st_api_get_current; + } + + return stapi; +} diff --git a/src/mesa/state_tracker/st_manager.h b/src/mesa/state_tracker/st_manager.h new file mode 100644 index 00000000000..a3f51992237 --- /dev/null +++ b/src/mesa/state_tracker/st_manager.h @@ -0,0 +1,47 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef ST_MANAGER_H +#define ST_MANAGER_H + +#include "state_tracker/st_api.h" +#include "st_context.h" + +void +st_manager_flush_frontbuffer(struct st_context *st); + +void +st_manager_validate_framebuffers(struct st_context *st); + +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx); + +struct st_api * +st_manager_create_api(void); + +#endif /* ST_MANAGER_H */ diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 10a38befb41..5809927852d 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -342,21 +342,12 @@ st_texture_image_copy(struct pipe_context *pipe, src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, PIPE_BUFFER_USAGE_GPU_READ); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - dst_surface, - 0, 0, /* destX, Y */ - src_surface, - 0, 0, /* srcX, Y */ - width, height); - } else { - util_surface_copy(pipe, FALSE, - dst_surface, - 0, 0, /* destX, Y */ - src_surface, - 0, 0, /* srcX, Y */ - width, height); - } + pipe->surface_copy(pipe, + dst_surface, + 0, 0, /* destX, Y */ + src_surface, + 0, 0, /* srcX, Y */ + width, height); pipe_surface_reference(&src_surface, NULL); pipe_surface_reference(&dst_surface, NULL); @@ -528,14 +519,21 @@ st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, /* save the renderbuffer's surface/texture info */ pipe_texture_reference(&strb->texture_save, strb->texture); pipe_surface_reference(&strb->surface_save, strb->surface); + pipe_sampler_view_reference(&strb->sampler_view_save, strb->sampler_view); /* plug in new surface/texture info */ pipe_texture_reference(&strb->texture, stImage->pt); + + /* XXX: Shouldn't we release reference to old surface here? + */ + strb->surface = screen->get_tex_surface(screen, strb->texture, face, level, slice, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + st->dirty.st |= ST_NEW_FRAMEBUFFER; return 1; @@ -565,9 +563,11 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex, /* free tex surface, restore original */ pipe_surface_reference(&strb->surface, strb->surface_save); pipe_texture_reference(&strb->texture, strb->texture_save); + pipe_sampler_view_reference(&strb->sampler_view, strb->sampler_view_save); pipe_surface_reference(&strb->surface_save, NULL); pipe_texture_reference(&strb->texture_save, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); st->dirty.st |= ST_NEW_FRAMEBUFFER; diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 60868ce0673..c62f7f2cc0d 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -29,6 +29,9 @@ #define ST_TEXTURE_H +#include "pipe/p_context.h" +#include "util/u_sampler.h" + #include "main/mtypes.h" struct pipe_context; @@ -68,6 +71,13 @@ struct st_texture_object */ struct pipe_texture *pt; + /* Default sampler view attached to this texture object. Created lazily + * on first binding. + */ + struct pipe_sampler_view *sampler_view; + + struct pipe_context *pipe; + GLboolean teximage_realloc; /* True if there is/was a surface bound to this texture object. It helps @@ -105,6 +115,35 @@ st_get_stobj_texture(struct st_texture_object *stObj) } +static INLINE struct pipe_sampler_view * +st_sampler_view_from_texture(struct pipe_context *pipe, + struct pipe_texture *texture) +{ + struct pipe_sampler_view templ; + + u_sampler_view_default_template(&templ, + texture, + texture->format); + + return pipe->create_sampler_view(pipe, texture, &templ); +} + + +static INLINE struct pipe_sampler_view * +st_get_stobj_sampler_view(struct st_texture_object *stObj) +{ + if (!stObj || !stObj->pt) { + return NULL; + } + + if (!stObj->sampler_view) { + stObj->sampler_view = st_sampler_view_from_texture(stObj->pipe, stObj->pt); + } + + return stObj->sampler_view; +} + + extern struct pipe_texture * st_texture_create(struct st_context *st, enum pipe_texture_target target, |