diff options
Diffstat (limited to 'src/mesa/state_tracker')
63 files changed, 2750 insertions, 1440 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index e29ab46ef9..bf160fe108 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -147,7 +147,11 @@ void st_validate_state( struct st_context *st ) /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/ +#ifdef NDEBUG + if (0) { +#else if (1) { +#endif /* Debug version which enforces various sanity checks on the * state flags which are generated and checked to help ensure * state atoms are ordered correctly in the list. diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c index a8ec4adce7..fb1c7a4efe 100644 --- a/src/mesa/state_tracker/st_atom_blend.c +++ b/src/mesa/state_tracker/st_atom_blend.c @@ -169,13 +169,18 @@ colormask_per_rt(struct gl_context *ctx) } /** - * Figure out if blend enables are different per rt. + * Figure out if blend enables/state are different per rt. */ static GLboolean blend_per_rt(struct gl_context *ctx) { if (ctx->Color.BlendEnabled && (ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) { + /* This can only happen if GL_EXT_draw_buffers2 is enabled */ + return GL_TRUE; + } + if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) { + /* this can only happen if GL_ARB_draw_buffers_blend is enabled */ return GL_TRUE; } return GL_FALSE; @@ -186,7 +191,7 @@ update_blend( struct st_context *st ) { struct pipe_blend_state *blend = &st->state.blend; unsigned num_state = 1; - unsigned i; + unsigned i, j; memset(blend, 0, sizeof(*blend)); @@ -202,39 +207,50 @@ update_blend( struct st_context *st ) don't happen. */ if (st->ctx->Color.ColorLogicOpEnabled || (st->ctx->Color.BlendEnabled && - st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) { + st->ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) { /* logicop enabled */ blend->logicop_enable = 1; blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp); } else if (st->ctx->Color.BlendEnabled) { /* blending enabled */ - for (i = 0; i < num_state; i++) { + for (i = 0, j = 0; i < num_state; i++) { blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1; - blend->rt[i].rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB); - if (st->ctx->Color.BlendEquationRGB == GL_MIN || - st->ctx->Color.BlendEquationRGB == GL_MAX) { + if (st->ctx->Extensions.ARB_draw_buffers_blend) + j = i; + + blend->rt[i].rgb_func = + translate_blend(st->ctx->Color.Blend[j].EquationRGB); + + if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN || + st->ctx->Color.Blend[i].EquationRGB == GL_MAX) { /* Min/max are special */ blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; } else { - blend->rt[i].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB); - blend->rt[i].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB); + blend->rt[i].rgb_src_factor = + translate_blend(st->ctx->Color.Blend[j].SrcRGB); + blend->rt[i].rgb_dst_factor = + translate_blend(st->ctx->Color.Blend[j].DstRGB); } - blend->rt[i].alpha_func = translate_blend(st->ctx->Color.BlendEquationA); - if (st->ctx->Color.BlendEquationA == GL_MIN || - st->ctx->Color.BlendEquationA == GL_MAX) { + blend->rt[i].alpha_func = + translate_blend(st->ctx->Color.Blend[j].EquationA); + + if (st->ctx->Color.Blend[i].EquationA == GL_MIN || + st->ctx->Color.Blend[i].EquationA == GL_MAX) { /* Min/max are special */ blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; } else { - blend->rt[i].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA); - blend->rt[i].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA); + blend->rt[i].alpha_src_factor = + translate_blend(st->ctx->Color.Blend[j].SrcA); + blend->rt[i].alpha_dst_factor = + translate_blend(st->ctx->Color.Blend[j].DstA); } } } diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index f1d08a3e16..05667a7430 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -56,7 +56,6 @@ void st_upload_constants( struct st_context *st, unsigned shader_type) { struct pipe_context *pipe = st->pipe; - struct pipe_resource **cbuf = &st->state.constants[shader_type]; assert(shader_type == PIPE_SHADER_VERTEX || shader_type == PIPE_SHADER_FRAGMENT || @@ -64,6 +63,7 @@ void st_upload_constants( struct st_context *st, /* update constants */ if (params && params->NumParameters) { + struct pipe_resource *cbuf; const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4; /* Update the constants which come from fixed-function state, such as @@ -75,11 +75,12 @@ void st_upload_constants( struct st_context *st, /* We always need to get a new buffer, to keep the drivers simple and * avoid gratuitous rendering synchronization. + * Let's use a user buffer to avoid an unnecessary copy. */ - pipe_resource_reference(cbuf, NULL ); - *cbuf = pipe_buffer_create(pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, - paramBytes ); + cbuf = pipe_user_buffer_create(pipe->screen, + params->ParameterValues, + paramBytes, + PIPE_BIND_CONSTANT_BUFFER); if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", @@ -88,17 +89,15 @@ void st_upload_constants( struct st_context *st, _mesa_print_parameter_list(params); } - /* load Mesa constants into the constant buffer */ - pipe_buffer_write(st->pipe, *cbuf, - 0, paramBytes, - params->ParameterValues); + st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf); + pipe_resource_reference(&cbuf, NULL); - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, *cbuf); + st->state.constants[shader_type].ptr = params->ParameterValues; + st->state.constants[shader_type].size = paramBytes; } - else if (*cbuf) { - st->constants.tracked_state[shader_type].dirty.mesa = 0x0; - - pipe_resource_reference(cbuf, NULL); + else if (st->state.constants[shader_type].ptr) { + st->state.constants[shader_type].ptr = NULL; + st->state.constants[shader_type].size = 0; st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL); } } diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 2843b7b176..76386fe017 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -39,7 +39,7 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" #include "util/u_inlines.h" - +#include "util/u_format.h" /** @@ -55,8 +55,10 @@ update_renderbuffer_surface(struct st_context *st, struct pipe_resource *resource = strb->rtt->pt; int rtt_width = strb->Base.Width; int rtt_height = strb->Base.Height; + enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); if (!strb->surface || + strb->surface->format != format || strb->surface->texture != resource || strb->surface->width != rtt_width || strb->surface->height != rtt_height) { @@ -67,7 +69,7 @@ update_renderbuffer_surface(struct st_context *st, u_minify(resource->height0, level) == rtt_height) { struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = resource->format; + surf_tmpl.format = format; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 378b30e57c..9557adc2d8 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -99,7 +99,7 @@ create_color_map_texture(struct gl_context *ctx) /* create texture for color map/table */ pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0, - texSize, texSize, 1, PIPE_BIND_SAMPLER_VIEW); + texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } @@ -187,7 +187,7 @@ get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key) inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0); - fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLOR); + fp->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ if (key->scaleAndBias) { diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index f92ca13d5e..8bccceeec5 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -70,14 +70,16 @@ static void update_raster_state( struct st_context *st ) { raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW); - /* XXX - * I think the intention here is that user-created framebuffer objects - * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout. - * Flipping Y changes CW to CCW and vice-versa. - * But this is an implementation/driver-specific artifact - remove... + /* + * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the + * opposite. Window system surfaces are Y=0=TOP. Mesa's FBOs + * must match OpenGL conventions so FBOs use Y=0=BOTTOM. In that + * case, we must invert Y and flip the notion of front vs. back. */ - if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { + /* Drawing to an FBO. The viewport will be inverted. */ raster->front_ccw ^= 1; + } } /* _NEW_LIGHT diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index b67068df37..474cbd5897 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -36,6 +36,7 @@ #include "st_context.h" #include "st_cb_texture.h" +#include "st_format.h" #include "st_atom.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -117,49 +118,6 @@ gl_filter_to_img_filter(GLenum filter) } -static void -xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut) -{ - switch (baseFormat) { - case GL_RED: - colorOut[0] = colorIn[0]; - colorOut[1] = 0.0F; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RG: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RGB: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = colorIn[2]; - colorOut[3] = 1.0F; - break; - case GL_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = 0.0; - colorOut[3] = colorIn[3]; - break; - case GL_LUMINANCE: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = 1.0; - break; - case GL_LUMINANCE_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = colorIn[3]; - break; - case GL_INTENSITY: - colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; - break; - default: - COPY_4V(colorOut, colorIn); - } -} - - static void update_samplers(struct st_context *st) { @@ -223,7 +181,7 @@ update_samplers(struct st_context *st) assert(sampler->min_lod <= sampler->max_lod); } - xlate_border_color(texobj->BorderColor.f, + st_translate_color(texobj->BorderColor.f, teximg ? teximg->_BaseFormat : GL_RGBA, sampler->border_color); diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 05442ef91b..c311d04393 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -50,99 +50,6 @@ #include "st_program.h" - -/** - * Translate fragment program if needed. - */ -static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) -{ - if (!stfp->tgsi.tokens) { - assert(stfp->Base.Base.NumInstructions > 0); - - st_translate_fragment_program(st, stfp); - } -} - -/* - * Translate geometry program if needed. - */ -static void -translate_gp(struct st_context *st, - struct st_geometry_program *stgp) -{ - if (!stgp->tgsi.tokens) { - assert(stgp->Base.Base.NumInstructions > 1); - - st_translate_geometry_program(st, stgp); - } -} - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. - */ -static struct st_vp_varient * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp ) -{ - struct st_vp_varient *vpv; - struct st_vp_varient_key key; - - /* Nothing in our key yet. This will change: - */ - memset(&key, 0, sizeof key); - - /* When this is true, we will add an extra input to the vertex - * shader translation (for edgeflags), an extra output with - * edgeflag semantics, and extend the vertex shader to pass through - * the input to the output. We'll need to use similar logic to set - * up the extra vertex_element input for edgeflags. - * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA - */ - key.passthrough_edgeflags = (st->vertdata_edgeflags && ( - st->ctx->Polygon.FrontMode != GL_FILL || - st->ctx->Polygon.BackMode != GL_FILL)); - - - /* Do we need to throw away old translations after a change in the - * GL program string? - */ - if (stvp->serialNo != stvp->lastSerialNo) { - /* These may have changed if the program string changed. - */ - st_prepare_vertex_program( st, stvp ); - - /* We are now up-to-date: - */ - stvp->lastSerialNo = stvp->serialNo; - } - - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. - */ - for (vpv = stvp->varients; vpv; vpv = vpv->next) { - if (memcmp(&vpv->key, &key, sizeof key) == 0) { - break; - } - } - - /* No? Perform new translation here. */ - if (!vpv) { - vpv = st_translate_vertex_program(st, stvp, &key); - if (!vpv) - return NULL; - - vpv->next = stvp->varients; - stvp->varients = vpv; - } - - return vpv; -} - - /** * Return pointer to a pass-through fragment shader. * This shader is used when a texture is missing/incomplete. @@ -167,12 +74,16 @@ static void update_fp( struct st_context *st ) { struct st_fragment_program *stfp; + struct st_fp_variant_key key; assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - translate_fp(st, stfp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->fp_variant = st_get_fp_variant(st, stfp, &key); st_reference_fragprog(st, &st->fp, stfp); @@ -182,7 +93,8 @@ update_fp( struct st_context *st ) cso_set_fragment_shader_handle(st->cso_context, fs); } else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + cso_set_fragment_shader_handle(st->cso_context, + st->fp_variant->driver_shader); } } @@ -206,6 +118,7 @@ static void update_vp( struct st_context *st ) { struct st_vertex_program *stvp; + struct st_vp_variant_key key; /* find active shader and params -- Should be covered by * ST_NEW_VERTEX_PROGRAM @@ -214,12 +127,26 @@ update_vp( struct st_context *st ) stvp = st_vertex_program(st->ctx->VertexProgram._Current); assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); - st->vp_varient = find_translated_vp(st, stvp); + memset(&key, 0, sizeof key); + key.st = st; /* variants are per-context */ + + /* When this is true, we will add an extra input to the vertex + * shader translation (for edgeflags), an extra output with + * edgeflag semantics, and extend the vertex shader to pass through + * the input to the output. We'll need to use similar logic to set + * up the extra vertex_element input for edgeflags. + * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA + */ + key.passthrough_edgeflags = (st->vertdata_edgeflags && ( + st->ctx->Polygon.FrontMode != GL_FILL || + st->ctx->Polygon.BackMode != GL_FILL)); + + st->vp_variant = st_get_vp_variant(st, stvp, &key); st_reference_vertprog(st, &st->vp, stvp); cso_set_vertex_shader_handle(st->cso_context, - st->vp_varient->driver_shader); + st->vp_variant->driver_shader); st->vertex_result_to_slot = stvp->result_to_output; } @@ -231,14 +158,16 @@ const struct st_tracked_state st_update_vp = { _NEW_POLYGON, /* mesa */ ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */ }, - update_vp /* update */ + update_vp /* update */ }; + + static void update_gp( struct st_context *st ) { - struct st_geometry_program *stgp; + struct st_gp_variant_key key; if (!st->ctx->GeometryProgram._Current) { cso_set_geometry_shader_handle(st->cso_context, NULL); @@ -248,18 +177,22 @@ update_gp( struct st_context *st ) stgp = st_geometry_program(st->ctx->GeometryProgram._Current); assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); - translate_gp(st, stgp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->gp_variant = st_get_gp_variant(st, stgp, &key); st_reference_geomprog(st, &st->gp, stgp); - cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader); + cso_set_geometry_shader_handle(st->cso_context, + st->gp_variant->driver_shader); } const struct st_tracked_state st_update_gp = { - "st_update_gp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_GEOMETRY_PROGRAM /* st */ + "st_update_gp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_GEOMETRY_PROGRAM /* st */ }, - update_gp /* update */ + update_gp /* update */ }; diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 029b040346..fd03669e66 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -45,6 +45,7 @@ #include "util/u_inlines.h" #include "cso_cache/cso_context.h" + /** * Combine depth texture mode with "swizzle" so that depth mode swizzling * takes place before texture swizzling, and return the resulting swizzle. @@ -54,8 +55,8 @@ * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. */ -static GLuint apply_depthmode(enum pipe_format format, - GLuint swizzle, GLenum depthmode) +static GLuint +apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode) { const struct util_format_description *desc = util_format_description(format); @@ -109,6 +110,7 @@ static GLuint apply_depthmode(enum pipe_format format, return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); } + /** * Return TRUE if the swizzling described by "swizzle" and * "depthmode" (for depth textures only) is different from the swizzling @@ -118,8 +120,9 @@ static GLuint apply_depthmode(enum pipe_format format, * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. */ -static boolean check_sampler_swizzle(struct pipe_sampler_view *sv, - GLuint swizzle, GLenum depthmode) +static boolean +check_sampler_swizzle(struct pipe_sampler_view *sv, + GLuint swizzle, GLenum depthmode) { swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); @@ -127,15 +130,15 @@ static boolean check_sampler_swizzle(struct pipe_sampler_view *sv, (sv->swizzle_g != GET_SWZ(swizzle, 1)) || (sv->swizzle_b != GET_SWZ(swizzle, 2)) || (sv->swizzle_a != GET_SWZ(swizzle, 3))) - return true; - return false; + return TRUE; + return FALSE; } + static INLINE struct pipe_sampler_view * st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, struct st_texture_object *stObj, enum pipe_format format) - { struct pipe_sampler_view templ; GLuint swizzle = apply_depthmode(stObj->pt->format, @@ -161,19 +164,20 @@ static INLINE struct pipe_sampler_view * st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, struct pipe_context *pipe, enum pipe_format format) - { if (!stObj || !stObj->pt) { return NULL; } if (!stObj->sampler_view) { - stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj, format); + stObj->sampler_view = + st_create_texture_sampler_view_from_stobj(pipe, stObj, format); } return stObj->sampler_view; } + static void update_textures(struct st_context *st) { @@ -214,17 +218,29 @@ update_textures(struct st_context *st) continue; } + /* Determine the format of the texture sampler view */ st_view_format = stObj->pt->format; { - struct st_texture_image *firstImage; - enum pipe_format firstImageFormat; - firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + const struct st_texture_image *firstImage = + st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + const gl_format texFormat = firstImage->base.TexFormat; + enum pipe_format firstImageFormat = + st_mesa_format_to_pipe_format(texFormat); + + if ((stObj->base.sRGBDecode == GL_SKIP_DECODE_EXT) && + (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { + /* don't do sRGB->RGB conversion. Interpret the texture + * texture data as linear values. + */ + const gl_format linearFormat = + _mesa_get_srgb_format_linear(texFormat); + firstImageFormat = st_mesa_format_to_pipe_format(linearFormat); + } - firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); if (firstImageFormat != stObj->pt->format) st_view_format = firstImageFormat; - } + st->state.num_textures = su + 1; /* if sampler view has changed dereference it */ diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c index d10f1840df..133cc49eaf 100644 --- a/src/mesa/state_tracker/st_atom_viewport.c +++ b/src/mesa/state_tracker/st_atom_viewport.c @@ -47,10 +47,14 @@ update_viewport( struct st_context *st ) /* _NEW_BUFFERS */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + /* Drawing to a window. The corresponding gallium surface uses + * Y=0=TOP but OpenGL is Y=0=BOTTOM. So we need to invert the viewport. + */ yScale = -1; yBias = (GLfloat)ctx->DrawBuffer->Height; } else { + /* Drawing to an FBO where Y=0=BOTTOM, like OpenGL - don't invert */ yScale = 1.0; yBias = 0.0; } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index a76ae92dc3..3e01c440bd 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "st_debug.h" #include "st_context.h" @@ -41,6 +42,7 @@ #include "st_texture.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -145,7 +147,9 @@ accum_accum(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -182,7 +186,6 @@ accum_load(struct st_context *st, GLfloat value, GLubyte *data = acc_strb->data; GLfloat *buf; - if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -193,7 +196,9 @@ accum_load(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -231,6 +236,7 @@ accum_return(struct gl_context *ctx, GLfloat value, size_t stride = acc_strb->stride; const GLubyte *data = acc_strb->data; GLfloat *buf; + enum pipe_format format = util_format_linear(color_strb->texture->format); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -249,7 +255,8 @@ accum_return(struct gl_context *ctx, GLfloat value, width, height); if (usage & PIPE_TRANSFER_READ) - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -278,7 +285,8 @@ accum_return(struct gl_context *ctx, GLfloat value, _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); free(buf); pipe->transfer_destroy(pipe, color_trans); diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h index b8c9c35003..050a21483e 100644 --- a/src/mesa/state_tracker/st_cb_accum.h +++ b/src/mesa/state_tracker/st_cb_accum.h @@ -30,7 +30,11 @@ #define ST_CB_ACCUM_H -#include "main/mtypes.h" +#include "main/mfeatures.h" + +struct dd_function_table; +struct gl_context; +struct gl_renderbuffer; #if FEATURE_accum diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index f08697fe23..49b196032b 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -34,6 +34,8 @@ #include "main/image.h" #include "main/bufferobj.h" #include "main/macros.h" +#include "main/mfeatures.h" +#include "main/pbo.h" #include "program/program.h" #include "program/prog_print.h" @@ -185,48 +187,47 @@ find_free_bit(uint bitfield) /** * Combine basic bitmap fragment program with the user-defined program. + * \param st current context + * \param fpIn the incoming fragment program + * \param fpOut the new fragment program which does fragment culling + * \param bitmap_sampler sampler number for the bitmap texture */ -static struct st_fragment_program * -combined_bitmap_fragment_program(struct gl_context *ctx) +void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp = st->fp; - - if (!stfp->bitmap_program) { - /* - * Generate new program which is the user-defined program prefixed - * with the bitmap sampler/kill instructions. - */ - struct st_fragment_program *bitmap_prog; - uint sampler; - - sampler = find_free_bit(st->fp->Base.Base.SamplersUsed); - bitmap_prog = make_bitmap_fragment_program(ctx, sampler); + struct st_fragment_program *bitmap_prog; + struct gl_program *newProg; + uint sampler; - stfp->bitmap_program = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &bitmap_prog->Base.Base, &stfp->Base.Base); - stfp->bitmap_program->bitmap_sampler = sampler; + /* + * Generate new program which is the user-defined program prefixed + * with the bitmap sampler/kill instructions. + */ + sampler = find_free_bit(fpIn->Base.SamplersUsed); + bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler); - /* done with this after combining */ - st_reference_fragprog(st, &bitmap_prog, NULL); + newProg = _mesa_combine_programs(st->ctx, + &bitmap_prog->Base.Base, + &fpIn->Base); + /* done with this after combining */ + st_reference_fragprog(st, &bitmap_prog, NULL); #if 0 - { - struct gl_program *p = &stfp->bitmap_program->Base.Base; - printf("Combined bitmap program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } -#endif - - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp->bitmap_program); + { + printf("Combined bitmap program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); } +#endif - return stfp->bitmap_program; + /* return results */ + *fpOut = (struct gl_fragment_program *) newProg; + *bitmap_sampler = sampler; } @@ -276,7 +277,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, * Create texture to hold bitmap pattern. */ pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format, - 0, width, height, 1, + 0, width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); @@ -349,7 +350,9 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, - max_slots * sizeof(st->bitmap.vertices)); + PIPE_USAGE_STREAM, + max_slots * + sizeof(st->bitmap.vertices)); } /* Positions are in clip coords since we need to do clipping in case @@ -389,10 +392,11 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, - st->bitmap.vbuf, - st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, - sizeof st->bitmap.vertices, - st->bitmap.vertices); + st->bitmap.vbuf, + st->bitmap.vbuf_slot + * sizeof(st->bitmap.vertices), + sizeof st->bitmap.vertices, + st->bitmap.vertices); return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices; } @@ -411,11 +415,16 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; - struct st_fragment_program *stfp; + struct st_fp_variant *fpv; + struct st_fp_variant_key key; GLuint maxSize; GLuint offset; - stfp = combined_bitmap_fragment_program(ctx); + memset(&key, 0, sizeof(key)); + key.st = st; + key.bitmap = GL_TRUE; + + fpv = st_get_fp_variant(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. @@ -428,7 +437,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } @@ -437,7 +446,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* XXX if the bitmap is larger than the max texture size, break * it up into chunks. */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + maxSize = 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); assert(width <= (GLsizei)maxSize); assert(height <= (GLsizei)maxSize); @@ -448,13 +458,14 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled; cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ - cso_set_fragment_shader_handle(cso, stfp->driver_shader); + cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); @@ -462,21 +473,22 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers); uint i; for (i = 0; i < st->state.num_samplers; i++) { samplers[i] = &st->state.samplers[i]; } - samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; + samplers[fpv->bitmap_sampler] = + &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures); memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); - sampler_views[stfp->bitmap_sampler] = sv; + sampler_views[fpv->bitmap_sampler] = sv; cso_set_fragment_sampler_views(cso, num, sampler_views); } @@ -504,9 +516,11 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, z = z * 2.0 - 1.0; /* draw textured quad */ - offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color); + offset = setup_bitmap_vertex_data(st, + sv->texture->target != PIPE_TEXTURE_RECT, + x, y, width, height, z, color); - util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset, + util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 3); /* attribs/vert */ @@ -520,6 +534,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } @@ -548,7 +563,7 @@ reset_cache(struct st_context *st) cache->texture = st_texture_create(st, PIPE_TEXTURE_2D, st->bitmap.tex_format, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - 1, + 1, 1, PIPE_BIND_SAMPLER_VIEW); } @@ -573,6 +588,9 @@ print_cache(const struct bitmap_cache *cache) } +/** + * Create gallium pipe_transfer object for the bitmap cache. + */ static void create_cache_trans(struct st_context *st) { @@ -651,7 +669,9 @@ st_flush_bitmap_cache(struct st_context *st) } } -/* Flush bitmap cache and release vertex buffer. + +/** + * Flush bitmap cache and release vertex buffer. */ void st_flush_bitmap( struct st_context *st ) @@ -737,7 +757,8 @@ accum_bitmap(struct st_context *st, * Called via ctx->Driver.Bitmap() */ static void -st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, +st_Bitmap(struct gl_context *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct st_context *st = st_context(ctx); @@ -764,7 +785,8 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei heigh pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { - struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); + struct pipe_sampler_view *sv = + st_create_texture_sampler_view(st->pipe, pt); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); @@ -814,16 +836,19 @@ st_init_bitmap(struct st_context *st) st->bitmap.rasterizer.gl_rasterization_rules = 1; /* find a usable texture format */ - if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; } else { @@ -845,8 +870,6 @@ st_destroy_bitmap(struct st_context *st) struct pipe_context *pipe = st->pipe; struct bitmap_cache *cache = st->bitmap.cache; - - if (st->bitmap.vs) { cso_delete_vertex_shader(st->cso_context, st->bitmap.vs); st->bitmap.vs = NULL; diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h index d04b2b6779..ed14158037 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.h +++ b/src/mesa/state_tracker/st_cb_bitmap.h @@ -31,9 +31,12 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; +struct gl_fragment_program; +struct st_fragment_program; #if FEATURE_drawpix @@ -47,6 +50,12 @@ extern void st_destroy_bitmap(struct st_context *st); extern void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler); + +extern void st_flush_bitmap_cache(struct st_context *st); /* Flush bitmap cache and release vertex buffer. Needed at end of diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 06cee520b3..6d02a7dccd 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "st_context.h" #include "st_texture.h" @@ -40,7 +41,6 @@ #include "st_cb_fbo.h" #include "util/u_blit.h" -#include "util/u_inlines.h" void diff --git a/src/mesa/state_tracker/st_cb_blit.h b/src/mesa/state_tracker/st_cb_blit.h index c230652cef..c6d9a36795 100644 --- a/src/mesa/state_tracker/st_cb_blit.h +++ b/src/mesa/state_tracker/st_cb_blit.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index 8b60f9040d..b9b606d539 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -171,7 +171,7 @@ st_bufferobj_data(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - unsigned buffer_usage; + unsigned bind, pipe_usage; st_obj->Base.Size = size; st_obj->Base.Usage = usage; @@ -179,22 +179,43 @@ st_bufferobj_data(struct gl_context *ctx, switch(target) { case GL_PIXEL_PACK_BUFFER_ARB: case GL_PIXEL_UNPACK_BUFFER_ARB: - buffer_usage = PIPE_BIND_RENDER_TARGET; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; break; case GL_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_VERTEX_BUFFER; + bind = PIPE_BIND_VERTEX_BUFFER; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_INDEX_BUFFER; + bind = PIPE_BIND_INDEX_BUFFER; break; default: - buffer_usage = 0; + bind = 0; + } + + switch (usage) { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + pipe_usage = PIPE_USAGE_STATIC; + break; + case GL_DYNAMIC_DRAW: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + pipe_usage = PIPE_USAGE_DYNAMIC; + break; + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + pipe_usage = PIPE_USAGE_STREAM; + break; + default: + pipe_usage = PIPE_USAGE_DEFAULT; } pipe_resource_reference( &st_obj->buffer, NULL ); if (size != 0) { - st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size); + st_obj->buffer = pipe_buffer_create(pipe->screen, bind, + pipe_usage, size); if (!st_obj->buffer) { return GL_FALSE; @@ -280,11 +301,15 @@ st_bufferobj_map_range(struct gl_context *ctx, GLenum target, if (access & GL_MAP_FLUSH_EXPLICIT_BIT) flags |= PIPE_TRANSFER_FLUSH_EXPLICIT; - if (access & GL_MAP_INVALIDATE_RANGE_BIT) - flags |= PIPE_TRANSFER_DISCARD; - - if (access & GL_MAP_INVALIDATE_BUFFER_BIT) - flags |= PIPE_TRANSFER_DISCARD; + if (access & GL_MAP_INVALIDATE_BUFFER_BIT) { + flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + } + else if (access & GL_MAP_INVALIDATE_RANGE_BIT) { + if (offset == 0 && length == obj->Size) + flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + else + flags |= PIPE_TRANSFER_DISCARD_RANGE; + } if (access & GL_MAP_UNSYNCHRONIZED_BIT) flags |= PIPE_TRANSFER_UNSYNCHRONIZED; @@ -360,7 +385,7 @@ st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_objec struct st_buffer_object *st_obj = st_buffer_object(obj); if (obj->Length) - pipe_buffer_unmap(pipe, st_obj->buffer, st_obj->transfer); + pipe_buffer_unmap(pipe, st_obj->transfer); st_obj->transfer = NULL; obj->Pointer = NULL; @@ -409,8 +434,8 @@ st_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr + writeOffset, srcPtr + readOffset, size); - pipe_buffer_unmap(pipe, srcObj->buffer, src_transfer); - pipe_buffer_unmap(pipe, dstObj->buffer, dst_transfer); + pipe_buffer_unmap(pipe, src_transfer); + pipe_buffer_unmap(pipe, dst_transfer); } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index bd1dd78b23..1eb748e0d5 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -42,6 +42,7 @@ #include "st_cb_accum.h" #include "st_cb_clear.h" #include "st_cb_fbo.h" +#include "st_format.h" #include "st_program.h" #include "pipe/p_context.h" @@ -62,26 +63,12 @@ void st_init_clear(struct st_context *st) { - struct pipe_context *pipe = st->pipe; struct pipe_screen *pscreen = st->pipe->screen; memset(&st->clear, 0, sizeof(st->clear)); st->clear.raster.gl_rasterization_rules = 1; st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE); - - /* fragment shader state: color pass-through program */ - st->clear.fs = util_make_fragment_passthrough_shader(pipe); - - /* vertex shader state: color/position pass-through */ - { - const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, - TGSI_SEMANTIC_COLOR }; - const uint semantic_indexes[] = { 0, 0 }; - st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2, - semantic_names, - semantic_indexes); - } } @@ -107,6 +94,42 @@ st_destroy_clear(struct st_context *st) /** + * Helper function to set the fragment shaders. + */ +static INLINE void +set_fragment_shader(struct st_context *st) +{ + if (!st->clear.fs) + st->clear.fs = util_make_fragment_passthrough_shader(st->pipe); + + cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); +} + + +/** + * Helper function to set the vertex shader. + */ +static INLINE void +set_vertex_shader(struct st_context *st) +{ + /* vertex shader - still required to provide the linkage between + * fragment shader input semantics and vertex_element/buffers. + */ + if (!st->clear.vs) + { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_COLOR }; + const uint semantic_indexes[] = { 0, 0 }; + st->clear.vs = util_make_vertex_passthrough_shader(st->pipe, 2, + semantic_names, + semantic_indexes); + } + + cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); +} + + +/** * Draw a screen-aligned quadrilateral. * Coords are clip coords with y=0=bottom. */ @@ -138,6 +161,7 @@ draw_quad(struct st_context *st, if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof(st->clear.vertices)); } @@ -172,7 +196,8 @@ draw_quad(struct st_context *st, st->clear.vertices); /* draw */ - util_draw_vertex_buffer(pipe, + util_draw_vertex_buffer(pipe, + st->cso_context, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, @@ -202,6 +227,7 @@ clear_with_quad(struct gl_context *ctx, const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; + float clearColor[4]; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -221,6 +247,7 @@ clear_with_quad(struct gl_context *ctx, cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); + cso_save_vertex_buffers(st->cso_context); /* blend state: RGBA masking */ { @@ -292,12 +319,17 @@ clear_with_quad(struct gl_context *ctx, } cso_set_clip(st->cso_context, &st->clear.clip); - cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); - cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); + set_fragment_shader(st); + set_vertex_shader(st); - /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(st, x0, y0, x1, y1, - (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + + /* draw quad matching scissor rect */ + draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, clearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); @@ -309,6 +341,7 @@ clear_with_quad(struct gl_context *ctx, cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); + cso_restore_vertex_buffers(st->cso_context); } @@ -470,13 +503,9 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; - struct st_renderbuffer *strb; - - assert(rb); + struct st_renderbuffer *strb = st_renderbuffer(rb); - strb = st_renderbuffer(rb); - - if (!strb->surface) + if (!strb || !strb->surface) continue; if (check_clear_color_with_quad( ctx, rb )) @@ -541,12 +570,21 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) * required from the visual. Hence fix this up to avoid potential * read-modify-write in the driver. */ + float clearColor[4]; + if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && (depthRb == stencilRb) && (ctx->DrawBuffer->Visual.depthBits == 0 || ctx->DrawBuffer->Visual.stencilBits == 0)) clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index c978602457..eccc207579 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -34,7 +34,10 @@ #include "main/image.h" #include "main/bufferobj.h" #include "main/macros.h" +#include "main/mfeatures.h" +#include "main/mtypes.h" #include "main/pack.h" +#include "main/pbo.h" #include "main/texformat.h" #include "main/texstore.h" #include "program/program.h" @@ -94,88 +97,61 @@ is_passthrough_program(const struct gl_fragment_program *prog) /** * Make fragment shader for glDraw/CopyPixels. This shader is made * by combining the pixel transfer shader with the user-defined shader. - * \return pointer to Gallium driver fragment shader + * \param fpIn the current/incoming fragment program + * \param fpOut returns the combined fragment program */ -static void * -combined_drawpix_fragment_program(struct gl_context *ctx) +void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp; + struct gl_program *newProg; - if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn - && st->fp->serialNo == st->pixel_xfer.user_prog_sn) { - /* the pixel tranfer program has not changed and the user-defined - * program has not changed, so re-use the combined program. - */ - stfp = st->pixel_xfer.combined_prog; + if (is_passthrough_program(fpIn)) { + newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, + &st->pixel_xfer.program->Base); } else { - /* Concatenate the pixel transfer program with the current user- - * defined program. - */ - if (is_passthrough_program(&st->fp->Base)) { - stfp = (struct st_fragment_program *) - _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base); - } - else { #if 0 - printf("Base program:\n"); - _mesa_print_program(&st->fp->Base.Base); - printf("DrawPix program:\n"); - _mesa_print_program(&st->pixel_xfer.program->Base.Base); + /* debug */ + printf("Base program:\n"); + _mesa_print_program(&fpIn->Base); + printf("DrawPix program:\n"); + _mesa_print_program(&st->pixel_xfer.program->Base.Base); #endif - stfp = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &st->pixel_xfer.program->Base.Base, - &st->fp->Base.Base); - } + newProg = _mesa_combine_programs(st->ctx, + &st->pixel_xfer.program->Base.Base, + &fpIn->Base); + } #if 0 - { - struct gl_program *p = &stfp->Base.Base; - printf("Combined DrawPixels program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } + /* debug */ + printf("Combined DrawPixels program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); #endif - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp); - - /* save new program, update serial numbers */ - st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; - st->pixel_xfer.user_prog_sn = st->fp->serialNo; - st->pixel_xfer.combined_prog_sn = stfp->serialNo; - /* can't reference new program directly, already have a reference on it */ - st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); - st->pixel_xfer.combined_prog = stfp; - } - - /* Ideally we'd have updated the pipe constants during the normal - * st/atom mechanism. But we can't since this is specific to glDrawPixels. - */ - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); - - return stfp->driver_shader; + *fpOut = (struct gl_fragment_program *) newProg; } /** - * Create fragment shader that does a TEX() instruction to get a Z and/or + * Create fragment program that does a TEX() instruction to get a Z and/or * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). * Pass fragment color through as-is. - * \return pointer to the Gallium driver fragment shader + * \return pointer to the gl_fragment program */ -static void * -make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, - GLboolean write_stencil) +struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil) { struct gl_context *ctx = st->ctx; struct gl_program *p; - struct st_fragment_program *stp; + struct gl_fragment_program *fp; GLuint ic = 0; const GLuint shaderIndex = write_depth * 2 + write_stencil; @@ -183,7 +159,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (st->drawpix.shaders[shaderIndex]) { /* already have the proper shader */ - return st->drawpix.shaders[shaderIndex]->driver_shader; + return st->drawpix.shaders[shaderIndex]; } /* @@ -237,26 +213,23 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; p->OutputsWritten = 0; if (write_depth) - p->OutputsWritten |= (1 << FRAG_RESULT_DEPTH); + p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH); if (write_stencil) - p->OutputsWritten |= (1 << FRAG_RESULT_STENCIL); + p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL); p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ if (write_stencil) p->SamplersUsed |= 1 << 1; - stp = st_fragment_program((struct gl_fragment_program *) p); + fp = (struct gl_fragment_program *) p; /* save the new shader */ - st->drawpix.shaders[shaderIndex] = stp; - - st_translate_fragment_program(st, stp); + st->drawpix.shaders[shaderIndex] = fp; - return stp->driver_shader; + return fp; } - /** * Create a simple vertex shader that just passes through the * vertex position and texcoord (and optionally, color). @@ -371,7 +344,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height, struct pipe_resource *pt; pt = st_texture_create(st, st->internal_target, texFormat, 0, - width, height, 1, PIPE_BIND_SAMPLER_VIEW); + width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } @@ -550,10 +523,11 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(verts)); pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts); - util_draw_vertex_buffer(pipe, buf, 0, + util_draw_vertex_buffer(pipe, st->cso_context, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ @@ -598,6 +572,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); if (write_stencil) { cso_save_depth_stencil_alpha(cso); cso_save_blend(cso); @@ -714,6 +689,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); @@ -873,6 +849,61 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for RGBA data. + */ +static struct st_fp_variant * +get_color_fp_variant(struct st_context *st) +{ + struct gl_context *ctx = st->ctx; + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 || + ctx->Pixel.RedScale != 1.0 || + ctx->Pixel.GreenBias != 0.0 || + ctx->Pixel.GreenScale != 1.0 || + ctx->Pixel.BlueBias != 0.0 || + ctx->Pixel.BlueScale != 1.0 || + ctx->Pixel.AlphaBias != 0.0 || + ctx->Pixel.AlphaScale != 1.0); + key.pixelMaps = ctx->Pixel.MapColorFlag; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for depth/stencil data. + */ +static struct st_fp_variant * +get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth, + GLboolean write_stencil) +{ + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.drawpixels_z = write_depth; + key.drawpixels_stencil = write_stencil; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** * Called via ctx->Driver.DrawPixels() */ static void @@ -889,6 +920,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; enum pipe_format stencil_format = PIPE_FORMAT_NONE; + struct st_fp_variant *fpv; if (format == GL_DEPTH_STENCIL) write_stencil = write_depth = GL_TRUE; @@ -921,14 +953,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, st_validate_state(st); + /* + * Get vertex/fragment shaders + */ if (write_depth || write_stencil) { - driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil); + fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); + color = ctx->Current.RasterColor; } else { - driver_fp = combined_drawpix_fragment_program(ctx); + fpv = get_color_fp_variant(st); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + color = NULL; if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; @@ -936,6 +979,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, } } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + /* draw with textured quad */ { struct pipe_resource *pt @@ -1097,6 +1143,110 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, } +/** Do the src/dest regions overlap? */ +static GLboolean +regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY, + GLsizei width, GLsizei height) +{ + if (srcX + width <= dstX || + dstX + width <= srcX || + srcY + height <= dstY || + dstY + height <= srcY) + return GL_FALSE; + else + return GL_TRUE; +} + + +/** + * Try to do a glCopyPixels for simple cases with a blit by calling + * pipe->resource_copy_region(). + * + * We can do this when we're copying color pixels (depth/stencil + * eventually) with no pixel zoom, no pixel transfer ops, no + * per-fragment ops, the src/dest regions don't overlap and the + * src/dest pixel formats are the same. + */ +static GLboolean +blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct gl_pixelstore_attrib pack, unpack; + GLint readX, readY, readW, readH; + + if (type == GL_COLOR && + ctx->Pixel.ZoomX == 1.0 && + ctx->Pixel.ZoomY == 1.0 && + ctx->_ImageTransferState == 0x0 && + !ctx->Color.BlendEnabled && + !ctx->Color.AlphaEnabled && + !ctx->Depth.Test && + !ctx->Fog.Enabled && + !ctx->Stencil.Enabled && + !ctx->FragmentProgram.Enabled && + !ctx->VertexProgram.Enabled && + !ctx->Shader.CurrentFragmentProgram && + st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && + ctx->DrawBuffer->_NumColorDrawBuffers == 1) { + struct st_renderbuffer *rbRead, *rbDraw; + GLint drawX, drawY; + + /* + * 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; + pack = ctx->DefaultPacking; + if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) + return GL_TRUE; /* all done */ + + /* clip against dest buffer bounds and scissor box */ + drawX = dstx + pack.SkipPixels; + drawY = dsty + pack.SkipRows; + unpack = pack; + if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) + return GL_TRUE; /* all done */ + + readX = readX - pack.SkipPixels + unpack.SkipPixels; + readY = readY - pack.SkipRows + unpack.SkipRows; + + rbRead = st_get_color_read_renderbuffer(ctx); + rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); + + if ((rbRead != rbDraw || + !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && + rbRead->Base.Format == rbDraw->Base.Format) { + struct pipe_box srcBox; + + /* flip src/dst position if needed */ + if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* both buffers will have the same orientation */ + readY = ctx->ReadBuffer->Height - readY - readH; + drawY = ctx->DrawBuffer->Height - drawY - readH; + } + + u_box_2d(readX, readY, readW, readH, &srcBox); + + pipe->resource_copy_region(pipe, + rbDraw->texture, 0, drawX, drawY, 0, + rbRead->texture, 0, &srcBox); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + static void st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, @@ -1116,6 +1266,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLint readX, readY, readW, readH; GLuint sample_count; struct gl_pixelstore_attrib pack = ctx->DefaultPacking; + struct st_fp_variant *fpv; st_validate_state(st); @@ -1125,11 +1276,29 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, return; } + if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) + return; + + /* + * The subsequent code implements glCopyPixels by copying the source + * pixels into a temporary texture that's then applied to a textured quad. + * When we draw the textured quad, all the usual per-fragment operations + * are handled. + */ + + + /* + * Get vertex/fragment shaders + */ if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; - driver_fp = combined_drawpix_fragment_program(ctx); + + fpv = get_color_fp_variant(st); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; @@ -1139,10 +1308,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; - driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE); + + fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + + if (rbRead->Base.Wrapped) rbRead = st_renderbuffer(rbRead->Base.Wrapped); @@ -1156,7 +1332,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (screen->is_format_supported(screen, srcFormat, st->internal_target, sample_count, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { texFormat = srcFormat; } else { @@ -1211,7 +1387,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (srcFormat == texFormat) { struct pipe_box src_box; u_box_2d(readX, readY, readW, readH, &src_box); - /* copy source framebuffer surface into mipmap/texture */ + /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ 0, @@ -1224,7 +1400,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, + pipe_get_transfer(st->pipe, rbRead->texture, + 0, 0, /* level, layer */ PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; @@ -1245,15 +1422,19 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, 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, readX, readY, readW, readH, buf); - pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, - readW, readH, buf); + enum pipe_format readFormat, drawFormat; + readFormat = util_format_linear(rbRead->texture->format); + drawFormat = util_format_linear(pt->format); + pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, + readFormat, buf); + pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, drawFormat, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, buf); free(buf); @@ -1294,7 +1475,7 @@ st_destroy_drawpix(struct st_context *st) for (i = 0; i < Elements(st->drawpix.shaders); i++) { if (st->drawpix.shaders[i]) - st_reference_fragprog(st, &st->drawpix.shaders[i], NULL); + _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); } st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index 575f169e08..44d7f5ed1e 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.h +++ b/src/mesa/state_tracker/st_cb_drawpixels.h @@ -31,6 +31,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; @@ -42,6 +43,16 @@ extern void st_init_drawpixels_functions(struct dd_function_table *functions); extern void st_destroy_drawpix(struct st_context *st); +extern void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut); + +extern struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil); + #else static INLINE void diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index 6cad7d3216..86ceb9d78b 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -15,6 +15,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "program/program.h" #include "program/prog_print.h" @@ -138,6 +139,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, /* create the vertex buffer */ vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, numAttribs * 4 * 4 * sizeof(GLfloat)); /* load vertex buffer */ @@ -220,7 +222,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } } - pipe_buffer_unmap(pipe, vbuffer, vbuffer_transfer); + pipe_buffer_unmap(pipe, vbuffer_transfer); #undef SET_ATTRIB } @@ -229,6 +231,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); { void *vs = lookup_shader(pipe, numAttribs, @@ -263,7 +266,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } - util_draw_vertex_buffer(pipe, vbuffer, + util_draw_vertex_buffer(pipe, cso, vbuffer, 0, /* offset */ PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -276,6 +279,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_restore_viewport(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } diff --git a/src/mesa/state_tracker/st_cb_drawtex.h b/src/mesa/state_tracker/st_cb_drawtex.h index d21262f897..455da04e67 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.h +++ b/src/mesa/state_tracker/st_cb_drawtex.h @@ -11,6 +11,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index c4b84de790..dfde821fc1 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -26,6 +26,7 @@ * Chia-I Wu <olv@lunarg.com> */ +#include "main/mfeatures.h" #include "main/texobj.h" #include "main/texfetch.h" #include "main/teximage.h" diff --git a/src/mesa/state_tracker/st_cb_eglimage.h b/src/mesa/state_tracker/st_cb_eglimage.h index b6e44d5aff..48567ed9da 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.h +++ b/src/mesa/state_tracker/st_cb_eglimage.h @@ -30,6 +30,7 @@ #define ST_CB_EGLIMAGE_H #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index cd718a31a1..0df04287ae 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -38,6 +38,7 @@ #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" @@ -61,7 +62,8 @@ * during window resize. */ static GLboolean -st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, +st_renderbuffer_alloc_storage(struct gl_context * ctx, + struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { @@ -75,12 +77,18 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *r if (strb->format != PIPE_FORMAT_NONE) format = strb->format; else - format = st_choose_renderbuffer_format(screen, internalFormat, rb->NumSamples); - + 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 */ @@ -231,6 +239,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) 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; @@ -387,7 +396,7 @@ st_render_texture(struct gl_context *ctx, /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = strb->texture->format; + surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; @@ -422,14 +431,11 @@ static void st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) { - struct st_context *st = st_context(ctx); struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); if (!strb) return; - st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); - strb->rtt = NULL; /* @@ -445,11 +451,14 @@ st_finish_render_texture(struct gl_context *ctx, * Validate a renderbuffer attachment for a particular set of bindings. */ static GLboolean -st_validate_attachment(struct pipe_screen *screen, +st_validate_attachment(struct gl_context *ctx, + struct pipe_screen *screen, const struct gl_renderbuffer_attachment *att, unsigned bindings) { const struct st_texture_object *stObj = st_texture_object(att->Texture); + enum pipe_format format; + gl_format texFormat; /* Only validate texture attachments for now, since * st_renderbuffer_alloc_storage makes sure that @@ -461,9 +470,22 @@ st_validate_attachment(struct pipe_screen *screen, if (!stObj) return GL_FALSE; - return screen->is_format_supported(screen, stObj->pt->format, + 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, 0); + stObj->pt->nr_samples, bindings); } @@ -525,20 +547,23 @@ st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, depth, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, &fb->Attachment[BUFFER_COLOR0 + i], PIPE_BIND_RENDER_TARGET)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; diff --git a/src/mesa/state_tracker/st_cb_feedback.c b/src/mesa/state_tracker/st_cb_feedback.c index 5c01856f03..9b85a39bed 100644 --- a/src/mesa/state_tracker/st_cb_feedback.c +++ b/src/mesa/state_tracker/st_cb_feedback.c @@ -40,6 +40,7 @@ #include "main/imports.h" #include "main/context.h" #include "main/feedback.h" +#include "main/mfeatures.h" #include "vbo/vbo.h" diff --git a/src/mesa/state_tracker/st_cb_feedback.h b/src/mesa/state_tracker/st_cb_feedback.h index f2342f5823..02e34e4027 100644 --- a/src/mesa/state_tracker/st_cb_feedback.h +++ b/src/mesa/state_tracker/st_cb_feedback.h @@ -31,6 +31,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 5a2343d3ae..0e27cb9a3f 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -76,7 +76,7 @@ display_front_buffer(struct st_context *st) } -void st_flush( struct st_context *st, uint pipeFlushFlags, +void st_flush( struct st_context *st, struct pipe_fence_handle **fence ) { FLUSH_CURRENT(st->ctx, 0); @@ -89,7 +89,7 @@ void st_flush( struct st_context *st, uint pipeFlushFlags, util_blit_flush(st->blit); util_gen_mipmap_flush(st->gen_mipmap); - st->pipe->flush( st->pipe, pipeFlushFlags, fence ); + st->pipe->flush( st->pipe, fence ); } @@ -100,10 +100,11 @@ void st_finish( struct st_context *st ) { struct pipe_fence_handle *fence = NULL; - st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + st_flush(st, &fence); if(fence) { - st->pipe->screen->fence_finish(st->pipe->screen, fence, 0); + st->pipe->screen->fence_finish(st->pipe->screen, fence, + PIPE_TIMEOUT_INFINITE); st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL); } } @@ -122,7 +123,7 @@ static void st_glFlush(struct gl_context *ctx) * synchronization issues. Calling finish() here will just hide * problems that need to be fixed elsewhere. */ - st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + st_flush(st, NULL); if (is_front_buffer_dirty(st)) { display_front_buffer(st); diff --git a/src/mesa/state_tracker/st_cb_flush.h b/src/mesa/state_tracker/st_cb_flush.h index 7672b4cf1d..598536ba04 100644 --- a/src/mesa/state_tracker/st_cb_flush.h +++ b/src/mesa/state_tracker/st_cb_flush.h @@ -40,7 +40,7 @@ extern void st_init_flush_functions(struct dd_function_table *functions); extern void -st_flush(struct st_context *st, uint pipeFlushFlags, +st_flush(struct st_context *st, struct pipe_fence_handle **fence); extern void diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 4d83fcc6cc..32694975d1 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -46,16 +46,13 @@ #include "st_cb_program.h" -static GLuint SerialNo = 1; - /** * Called via ctx->Driver.BindProgram() to bind an ARB vertex or * fragment program. */ -static void st_bind_program( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +static void +st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -77,7 +74,8 @@ static void st_bind_program( struct gl_context *ctx, * Called via ctx->Driver.UseProgram() to bind a linked GLSL program * (vertex shader + fragment shader). */ -static void st_use_program( struct gl_context *ctx, struct gl_shader_program *shProg) +static void +st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) { struct st_context *st = st_context(ctx); @@ -87,48 +85,28 @@ static void st_use_program( struct gl_context *ctx, struct gl_shader_program *sh } - /** * Called via ctx->Driver.NewProgram() to allocate a new vertex or * fragment program. */ -static struct gl_program *st_new_program( struct gl_context *ctx, - GLenum target, - GLuint id ) +static struct gl_program * +st_new_program(struct gl_context *ctx, GLenum target, GLuint id) { switch (target) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_vertex_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_vertex_program(ctx, &prog->Base, target, id); } case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_NV: { struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_fragment_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_fragment_program(ctx, &prog->Base, target, id); } case MESA_GEOMETRY_PROGRAM: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_geometry_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_geometry_program(ctx, &prog->Base, target, id); } default: @@ -138,7 +116,10 @@ static struct gl_program *st_new_program( struct gl_context *ctx, } -void +/** + * Called via ctx->Driver.DeleteProgram() + */ +static void st_delete_program(struct gl_context *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -147,17 +128,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); } break; case MESA_GEOMETRY_PROGRAM: { - struct st_geometry_program *stgp = (struct st_geometry_program *) prog; + struct st_geometry_program *stgp = + (struct st_geometry_program *) prog; - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -167,23 +146,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) break; case GL_FRAGMENT_PROGRAM_ARB: { - struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + struct st_fragment_program *stfp = + (struct st_fragment_program *) prog; - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } - - if (stfp->bitmap_program) { - struct gl_program *prg = &stfp->bitmap_program->Base.Base; - _mesa_reference_program(ctx, &prg, NULL); - stfp->bitmap_program = NULL; - } } break; default: @@ -195,15 +166,25 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) } -static GLboolean st_is_program_native( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +/** + * Called via ctx->Driver.IsProgramNative() + */ +static GLboolean +st_is_program_native(struct gl_context *ctx, + GLenum target, + struct gl_program *prog) { return GL_TRUE; } -static GLboolean st_program_string_notify( struct gl_context *ctx, +/** + * Called via ctx->Driver.ProgramStringNotify() + * Called when the program's text/code is changed. We have to free + * all shader variants and corresponding gallium shaders when this happens. + */ +static GLboolean +st_program_string_notify( struct gl_context *ctx, GLenum target, struct gl_program *prog ) { @@ -212,12 +193,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; - stfp->serialNo++; - - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); @@ -230,12 +206,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == MESA_GEOMETRY_PROGRAM) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - stgp->serialNo++; - - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -248,9 +219,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - stvp->serialNo++; - - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; @@ -261,8 +230,11 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, } - -void st_init_program_functions(struct dd_function_table *functions) +/** + * Plug in the program and shader-related device driver functions. + */ +void +st_init_program_functions(struct dd_function_table *functions) { functions->BindProgram = st_bind_program; functions->UseProgram = st_use_program; diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h index 004afb6d81..091a4439c4 100644 --- a/src/mesa/state_tracker/st_cb_program.h +++ b/src/mesa/state_tracker/st_cb_program.h @@ -29,15 +29,10 @@ #define ST_CB_PROGRAM_H -#include "main/mtypes.h" - struct dd_function_table; extern void st_init_program_functions(struct dd_function_table *functions); -extern void -st_delete_program(struct gl_context *ctx, struct gl_program *prog); - #endif diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c index aa31b3710b..d0ac253bce 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.c +++ b/src/mesa/state_tracker/st_cb_queryobj.c @@ -35,6 +35,7 @@ #include "main/imports.h" #include "main/context.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -84,6 +85,8 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q) /* convert GL query type to Gallium query type */ switch (q->Target) { + case GL_ANY_SAMPLES_PASSED: + /* fall-through */ case GL_SAMPLES_PASSED_ARB: type = PIPE_QUERY_OCCLUSION_COUNTER; break; diff --git a/src/mesa/state_tracker/st_cb_queryobj.h b/src/mesa/state_tracker/st_cb_queryobj.h index 017471b0b0..03f0be8372 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.h +++ b/src/mesa/state_tracker/st_cb_queryobj.h @@ -29,6 +29,7 @@ #define ST_CB_QUERYOBJ_H +#include "main/mfeatures.h" #include "main/mtypes.h" /** diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c index 15a4f602d1..32d465c5cc 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -38,6 +38,7 @@ #include "main/imports.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "main/feedback.h" #include "st_context.h" diff --git a/src/mesa/state_tracker/st_cb_rasterpos.h b/src/mesa/state_tracker/st_cb_rasterpos.h index 2dc109bb18..b61411bd20 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.h +++ b/src/mesa/state_tracker/st_cb_rasterpos.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 0507be7457..f8da2a4d15 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -38,9 +38,11 @@ #include "main/context.h" #include "main/image.h" #include "main/pack.h" +#include "main/pbo.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -336,6 +338,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h struct st_renderbuffer *strb; struct gl_pixelstore_attrib clippedPacking = *pack; struct pipe_transfer *trans; + enum pipe_format pformat; assert(ctx->ReadBuffer->Width > 0); @@ -421,6 +424,9 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h yStep = 1; } + /* possibly convert sRGB format to linear RGB format */ + pformat = util_format_linear(trans->resource->format); + if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -435,8 +441,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, format, type); - if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || - trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) { + if (pformat == PIPE_FORMAT_Z24_UNORM_S8_USCALED || + pformat == PIPE_FORMAT_Z24X8_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -467,8 +473,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || - trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) { + else if (pformat == PIPE_FORMAT_S8_USCALED_Z24_UNORM || + pformat == PIPE_FORMAT_X8Z24_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -494,7 +500,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) { + else if (pformat == PIPE_FORMAT_Z16_UNORM) { for (i = 0; i < height; i++) { GLushort ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -509,7 +515,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h dst += dstStride; } } - else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) { + else if (pformat == PIPE_FORMAT_Z32_UNORM) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -528,7 +534,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h /* RGBA format */ /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { - pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df); + pipe_get_tile_rgba_format(pipe, trans, 0, y, width, 1, + pformat, df); y += yStep; df += dfStride; if (!dfStride) { diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h index 83c9b659e3..9622ae6fee 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.h +++ b/src/mesa/state_tracker/st_cb_readpixels.h @@ -29,9 +29,11 @@ #ifndef ST_CB_READPIXELS_H #define ST_CB_READPIXELS_H -#include "main/mtypes.h" +#include "main/glheader.h" struct dd_function_table; +struct gl_context; +struct gl_pixelstore_attrib; extern struct st_renderbuffer * st_get_color_read_renderbuffer(struct gl_context *ctx); diff --git a/src/mesa/state_tracker/st_cb_syncobj.c b/src/mesa/state_tracker/st_cb_syncobj.c new file mode 100644 index 0000000000..d575a84974 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_syncobj.c @@ -0,0 +1,122 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <maraeo@gmail.com> + * 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 AUTHORS 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. + * + **************************************************************************/ + + /* + * Authors: + * Marek Olšák <maraeo@gmail.com> + */ + +#include "main/glheader.h" +#include "main/macros.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "st_context.h" +#include "st_cb_syncobj.h" + +struct st_sync_object { + struct gl_sync_object b; + + struct pipe_fence_handle *fence; +}; + + +static struct gl_sync_object * st_new_sync_object(struct gl_context *ctx, + GLenum type) +{ + if (type == GL_SYNC_FENCE) + return (struct gl_sync_object*)CALLOC_STRUCT(st_sync_object); + else + return NULL; +} + +static void st_delete_sync_object(struct gl_context *ctx, + struct gl_sync_object *obj) +{ + struct pipe_screen *screen = st_context(ctx)->pipe->screen; + struct st_sync_object *so = (struct st_sync_object*)obj; + + screen->fence_reference(screen, &so->fence, NULL); + FREE(so); +} + +static void st_fence_sync(struct gl_context *ctx, struct gl_sync_object *obj, + GLenum condition, GLbitfield flags) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_sync_object *so = (struct st_sync_object*)obj; + + assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); + assert(so->fence == NULL); + + pipe->flush(pipe, &so->fence); +} + +static void st_check_sync(struct gl_context *ctx, struct gl_sync_object *obj) +{ + struct pipe_screen *screen = st_context(ctx)->pipe->screen; + struct st_sync_object *so = (struct st_sync_object*)obj; + + if (so->fence && screen->fence_signalled(screen, so->fence)) { + screen->fence_reference(screen, &so->fence, NULL); + so->b.StatusFlag = GL_TRUE; + } +} + +static void st_client_wait_sync(struct gl_context *ctx, + struct gl_sync_object *obj, + GLbitfield flags, GLuint64 timeout) +{ + struct pipe_screen *screen = st_context(ctx)->pipe->screen; + struct st_sync_object *so = (struct st_sync_object*)obj; + + /* We don't care about GL_SYNC_FLUSH_COMMANDS_BIT, because flush is + * already called when creating a fence. */ + + if (so->fence && + screen->fence_finish(screen, so->fence, timeout)) { + screen->fence_reference(screen, &so->fence, NULL); + so->b.StatusFlag = GL_TRUE; + } +} + +static void st_server_wait_sync(struct gl_context *ctx, + struct gl_sync_object *obj, + GLbitfield flags, GLuint64 timeout) +{ + /* NO-OP. + * Neither Gallium nor DRM interfaces support blocking on the GPU. */ +} + +void st_init_syncobj_functions(struct dd_function_table *functions) +{ + functions->NewSyncObject = st_new_sync_object; + functions->FenceSync = st_fence_sync; + functions->DeleteSyncObject = st_delete_sync_object; + functions->CheckSync = st_check_sync; + functions->ClientWaitSync = st_client_wait_sync; + functions->ServerWaitSync = st_server_wait_sync; +} diff --git a/src/mesa/state_tracker/st_cb_syncobj.h b/src/mesa/state_tracker/st_cb_syncobj.h new file mode 100644 index 0000000000..c254684780 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_syncobj.h @@ -0,0 +1,38 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <maraeo@gmail.com> + * 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 AUTHORS 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. + * + **************************************************************************/ + +#ifndef ST_CB_SYNCOBJ_H +#define ST_CB_SYNCOBJ_H + + +struct dd_function_table; + +extern void +st_init_syncobj_functions(struct dd_function_table *functions); + + +#endif /* ST_CB_SYNCOBJ_H */ diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 866426a754..9d5eb113ff 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -35,6 +35,7 @@ #include "main/macros.h" #include "main/mipmap.h" #include "main/pack.h" +#include "main/pbo.h" #include "main/pixeltransfer.h" #include "main/texcompress.h" #include "main/texfetch.h" @@ -74,19 +75,18 @@ gl_target_to_pipe(GLenum target) switch (target) { case GL_TEXTURE_1D: return PIPE_TEXTURE_1D; - case GL_TEXTURE_2D: return PIPE_TEXTURE_2D; - case GL_TEXTURE_RECTANGLE_NV: return PIPE_TEXTURE_RECT; - case GL_TEXTURE_3D: return PIPE_TEXTURE_3D; - case GL_TEXTURE_CUBE_MAP_ARB: return PIPE_TEXTURE_CUBE; - + case GL_TEXTURE_1D_ARRAY_EXT: + return PIPE_TEXTURE_1D_ARRAY; + case GL_TEXTURE_2D_ARRAY_EXT: + return PIPE_TEXTURE_2D_ARRAY; default: assert(0); return 0; @@ -217,7 +217,6 @@ default_bindings(struct st_context *st, enum pipe_format format) { struct pipe_screen *screen = st->pipe->screen; const unsigned target = PIPE_TEXTURE_2D; - const unsigned geom = 0x0; unsigned bindings; if (util_format_is_depth_or_stencil(format)) @@ -225,10 +224,17 @@ default_bindings(struct st_context *st, enum pipe_format format) else bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - if (screen->is_format_supported(screen, format, target, 0, bindings, geom)) + if (screen->is_format_supported(screen, format, target, 0, bindings)) return bindings; - else - return PIPE_BIND_SAMPLER_VIEW; + else { + /* Try non-sRGB. */ + format = util_format_linear(format); + + if (screen->is_format_supported(screen, format, target, 0, bindings)) + return bindings; + else + return PIPE_BIND_SAMPLER_VIEW; + } } @@ -261,6 +267,55 @@ get_texture_dims(GLenum target) /** + * Given the size of a mipmap image, try to compute the size of the level=0 + * mipmap image. + * + * Note that this isn't always accurate for odd-sized, non-POW textures. + * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. + * + * \return GL_TRUE for success, GL_FALSE for failure + */ +static GLboolean +guess_base_level_size(GLenum target, + GLuint width, GLuint height, GLuint depth, GLuint level, + GLuint *width0, GLuint *height0, GLuint *depth0) +{ + const GLuint dims = get_texture_dims(target); + + assert(width >= 1); + assert(height >= 1); + assert(depth >= 1); + + if (level > 0) { + /* Depending on the image's size, we can't always make a guess here */ + if ((dims >= 1 && width == 1) || + (dims >= 2 && height == 1) || + (dims >= 3 && depth == 1)) { + /* we can't determine the image size at level=0 */ + return GL_FALSE; + } + + /* grow the image size until we hit level = 0 */ + while (level > 0) { + if (width > 1) + width <<= 1; + if (height > 1) + height <<= 1; + if (depth > 1) + depth <<= 1; + level--; + } + } + + *width0 = width; + *height0 = height; + *depth0 = depth; + + return GL_TRUE; +} + + +/** * Try to allocate a pipe_resource object for the given st_texture_object. * * We use the given st_texture_image as a clue to determine the size of the @@ -273,50 +328,27 @@ guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - const GLuint dims = get_texture_dims(stObj->base.Target); - GLuint level, lastLevel, width, height, depth; + GLuint lastLevel, width, height, depth; GLuint bindings; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - level = stImage->level; - width = stImage->base.Width2; /* size w/out border */ - height = stImage->base.Height2; - depth = stImage->base.Depth2; - - assert(width > 0); - assert(height > 0); - assert(depth > 0); - - /* Depending on the image's size, we can't always make a guess here. - */ - if (level > 0) { - if ( (dims >= 1 && width == 1) || - (dims >= 2 && height == 1) || - (dims >= 3 && depth == 1) ) { - /* we can't determine the image size at level=0 */ - stObj->width0 = stObj->height0 = stObj->depth0 = 0; - /* this is not an out of memory error */ - return GL_TRUE; - } + if (!guess_base_level_size(stObj->base.Target, + stImage->base.Width2, + stImage->base.Height2, + stImage->base.Depth2, + stImage->level, + &width, &height, &depth)) { + /* we can't determine the image size at level=0 */ + stObj->width0 = stObj->height0 = stObj->depth0 = 0; + /* this is not an out of memory error */ + return GL_TRUE; } - /* grow the image size until we hit level = 0 */ - while (level > 0) { - if (width != 1) - width <<= 1; - if (height != 1) - height <<= 1; - if (depth != 1) - depth <<= 1; - level--; - } - - assert(level == 0); - /* At this point, (width x height x depth) is the expected size of * the level=0 mipmap image. */ @@ -353,13 +385,18 @@ guess_and_alloc_texture(struct st_context *st, bindings = default_bindings(st, fmt); + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, + width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), fmt, lastLevel, - width, - height, - depth, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); @@ -407,125 +444,6 @@ strip_texture_border(GLint border, /** - * Try to do texture compression via rendering. If the Gallium driver - * can render into a compressed surface this will allow us to do texture - * compression. - * \return GL_TRUE for success, GL_FALSE for failure - */ -static GLboolean -compress_with_blit(struct gl_context * ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_image *texImage) -{ - const GLuint dstImageOffsets[1] = {0}; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - gl_format mesa_format; - struct pipe_resource templ; - struct pipe_resource *src_tex; - struct pipe_sampler_view view_templ; - struct pipe_sampler_view *src_view; - struct pipe_surface *dst_surface, surf_tmpl; - struct pipe_transfer *tex_xfer; - void *map; - - if (!stImage->pt) { - /* XXX: Can this happen? Should we assert? */ - return GL_FALSE; - } - - /* get destination surface (in the compressed texture) */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = stImage->level; - surf_tmpl.u.tex.first_layer = stImage->face; - surf_tmpl.u.tex.last_layer = stImage->face; - dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); - if (!dst_surface) { - /* can't render into this format (or other problem) */ - return GL_FALSE; - } - - /* Choose format for the temporary RGBA texture image. - */ - mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type); - assert(mesa_format); - if (!mesa_format) - return GL_FALSE; - - /* Create the temporary source texture - */ - memset(&templ, 0, sizeof(templ)); - templ.target = st->internal_target; - templ.format = st_mesa_format_to_pipe_format(mesa_format); - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - templ.usage = PIPE_USAGE_DEFAULT; - templ.bind = PIPE_BIND_SAMPLER_VIEW; - src_tex = screen->resource_create(screen, &templ); - - if (!src_tex) - return GL_FALSE; - - /* Put user's tex data into the temporary texture - */ - tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, - 0, 0, /* layer, level are zero */ - PIPE_TRANSFER_WRITE, - 0, 0, width, height); /* x, y, w, h */ - map = pipe_transfer_map(pipe, tex_xfer); - - _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, - map, /* dest ptr */ - 0, 0, 0, /* dest x/y/z offset */ - tex_xfer->stride, /* dest row stride (bytes) */ - dstImageOffsets, /* image offsets (for 3D only) */ - width, height, 1, /* size */ - format, type, /* source format/type */ - pixels, /* source data */ - unpack); /* source data packing */ - - pipe_transfer_unmap(pipe, tex_xfer); - pipe->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(st->blit, - src_view, /* sampler view (src) */ - 0, 0, /* src x0, y0 */ - width, height, /* src x1, y1 */ - dst_surface, /* pipe_surface (dst) */ - xoffset, yoffset, /* dst x0, y0 */ - xoffset + width, /* dst x1 */ - yoffset + height, /* dst y1 */ - 0.0, /* z */ - PIPE_TEX_MIPFILTER_NEAREST); - - pipe_surface_reference(&dst_surface, NULL); - pipe_resource_reference(&src_tex, NULL); - pipe_sampler_view_reference(&src_view, NULL); - - return GL_TRUE; -} - - -/** * Do glTexImage1/2/3D(). */ static void @@ -542,7 +460,6 @@ st_TexImage(struct gl_context * ctx, GLsizei imageSize, GLboolean compressed_src) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride = 0; @@ -669,22 +586,10 @@ st_TexImage(struct gl_context * ctx, pixels, unpack, "glTexImage"); } - /* See if we can do texture compression with a blit/render. - */ - if (!compressed_src && - !ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (!pixels) - goto done; - - if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, - format, type, pixels, unpack, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* @@ -918,6 +823,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, else { /* format translation via floats */ GLuint row; + enum pipe_format format = util_format_linear(dst_texture->format); for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLfloat rgba[4 * MAX_WIDTH]; @@ -928,7 +834,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba); + pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, + format, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -1073,7 +980,6 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; const GLuint srcImageStride = @@ -1093,20 +999,10 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, if (!pixels) return; - /* See if we can do texture compression with a blit/render. - */ - if (!ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (compress_with_blit(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* Map buffer if necessary. Need to lock to prevent other contexts @@ -1387,7 +1283,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc); + pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height, + util_format_linear(strb->texture->format), + tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -1528,6 +1426,9 @@ st_copy_texsubimage(struct gl_context *ctx, if (texBaseFormat == GL_DEPTH_COMPONENT || texBaseFormat == GL_DEPTH_STENCIL) { strb = st_renderbuffer(fb->_DepthBuffer); + if (strb->Base.Wrapped) { + strb = st_renderbuffer(strb->Base.Wrapped); + } } else { /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ @@ -1621,17 +1522,15 @@ st_copy_texsubimage(struct gl_context *ctx, texBaseFormat != GL_DEPTH_STENCIL && screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, sample_count, - PIPE_BIND_SAMPLER_VIEW, - 0) && + PIPE_BIND_SAMPLER_VIEW) && screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, - 0)) { + PIPE_BIND_RENDER_TARGET)) { /* draw textured quad to do the copy */ GLint srcY0, srcY1; struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; + surf_tmpl.format = util_format_linear(stImage->pt->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = stImage->level; surf_tmpl.u.tex.first_layer = stImage->face + destZ; @@ -1831,6 +1730,7 @@ st_finalize_texture(struct gl_context *ctx, GLuint face; struct st_texture_image *firstImage; enum pipe_format firstImageFormat; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1855,9 +1755,8 @@ st_finalize_texture(struct gl_context *ctx, * will match. */ if (firstImage->pt && - stObj->pt && firstImage->pt != stObj->pt && - firstImage->pt->last_level >= stObj->pt->last_level) { + (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) { pipe_resource_reference(&stObj->pt, firstImage->pt); pipe_sampler_view_reference(&stObj->sampler_view, NULL); } @@ -1865,6 +1764,24 @@ st_finalize_texture(struct gl_context *ctx, /* Find gallium format for the Mesa texture */ firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); + /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ + { + GLuint width, height, depth; + if (!guess_base_level_size(stObj->base.Target, + firstImage->base.Width2, + firstImage->base.Height2, + firstImage->base.Depth2, + stObj->base.BaseLevel, + &width, &height, &depth)) { + width = stObj->width0; + height = stObj->height0; + depth = stObj->depth0; + } + /* convert GL dims to Gallium dims */ + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + } + /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ @@ -1872,9 +1789,10 @@ st_finalize_texture(struct gl_context *ctx, if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != stObj->width0 || - stObj->pt->height0 != stObj->height0 || - stObj->pt->depth0 != stObj->depth0) + stObj->pt->width0 != ptWidth || + stObj->pt->height0 != ptHeight || + stObj->pt->depth0 != ptDepth || + stObj->pt->array_size != ptLayers) { /* The gallium texture does not match the Mesa texture so delete the * gallium texture now. We'll make a new one below. @@ -1894,9 +1812,10 @@ st_finalize_texture(struct gl_context *ctx, gl_target_to_pipe(stObj->base.Target), firstImageFormat, stObj->lastLevel, - stObj->width0, - stObj->height0, - stObj->depth0, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); if (!stObj->pt) { diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h index 60987055eb..f1502bda78 100644 --- a/src/mesa/state_tracker/st_cb_texture.h +++ b/src/mesa/state_tracker/st_cb_texture.h @@ -31,9 +31,10 @@ #include "main/glheader.h" -#include "main/mtypes.h" struct dd_function_table; +struct gl_context; +struct gl_texture_object; struct pipe_context; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_texturebarrier.c b/src/mesa/state_tracker/st_cb_texturebarrier.c new file mode 100644 index 0000000000..2f1a22b588 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_texturebarrier.c @@ -0,0 +1,60 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + + +/** + * glTextureBarrierNV function + * + * \author Marek Olšák + */ + + +#include "main/imports.h" +#include "main/context.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "st_context.h" +#include "st_cb_texturebarrier.h" + + +/** + * Called via ctx->Driver.TextureBarrier() + */ +static void +st_TextureBarrier(struct gl_context *ctx) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + pipe->texture_barrier(pipe); +} + + +void st_init_texture_barrier_functions(struct dd_function_table *functions) +{ + functions->TextureBarrier = st_TextureBarrier; +} diff --git a/src/mesa/state_tracker/st_cb_texturebarrier.h b/src/mesa/state_tracker/st_cb_texturebarrier.h new file mode 100644 index 0000000000..3b7d3776fd --- /dev/null +++ b/src/mesa/state_tracker/st_cb_texturebarrier.h @@ -0,0 +1,37 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +#ifndef ST_CB_TEXTUREBARRIER_H +#define ST_CB_TEXTUREBARRIER_H + + +struct dd_function_table; + +extern void st_init_texture_barrier_functions(struct dd_function_table *functions); + + +#endif diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c index 838a0a4a93..e415b186aa 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.c +++ b/src/mesa/state_tracker/st_cb_xformfb.c @@ -35,6 +35,7 @@ #include "main/imports.h" #include "main/context.h" +#include "main/mfeatures.h" #include "main/transformfeedback.h" #include "st_cb_xformfb.h" diff --git a/src/mesa/state_tracker/st_cb_xformfb.h b/src/mesa/state_tracker/st_cb_xformfb.h index 574cf481e1..1215ebea87 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.h +++ b/src/mesa/state_tracker/st_cb_xformfb.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 6ec9c699a2..5a39ab0a11 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -51,7 +51,9 @@ #include "st_cb_texture.h" #include "st_cb_xformfb.h" #include "st_cb_flush.h" +#include "st_cb_syncobj.h" #include "st_cb_strings.h" +#include "st_cb_texturebarrier.h" #include "st_cb_viewport.h" #include "st_atom.h" #include "st_draw.h" @@ -178,7 +180,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); - ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL); + ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL); /* XXX: need a capability bit in gallium to query if the pipe * driver prefers DP4 or MUL/MAD for vertex transformation. @@ -203,14 +205,13 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawpix(st); st_destroy_drawtex(st); - for (i = 0; i < Elements(st->state.sampler_views); i++) { - pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); } - for (i = 0; i < Elements(st->state.constants); i++) { - if (st->state.constants[i]) { - pipe_resource_reference(&st->state.constants[i], NULL); - } + for (i = 0; i < Elements(st->state.sampler_views); i++) { + pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } if (st->default_texture) { @@ -245,13 +246,14 @@ void st_destroy_context( struct st_context *st ) for (i = 0; i < PIPE_SHADER_TYPES; i++) { pipe->set_constant_buffer(pipe, i, 0, NULL); - pipe_resource_reference(&st->state.constants[i], NULL); } _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache); _vbo_DestroyContext(st->ctx); + st_destroy_program_variants(st); + _mesa_free_context_data(ctx); st_destroy_context_priv(st); @@ -287,11 +289,13 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_cond_render_functions(functions); st_init_readpixels_functions(functions); st_init_texture_functions(functions); + st_init_texture_barrier_functions(functions); st_init_flush_functions(functions); st_init_string_functions(functions); st_init_viewport_functions(functions); st_init_xformfb_functions(functions); + st_init_syncobj_functions(functions); functions->UpdateState = st_invalidate_state; } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index d342c0cff1..77765f0237 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -1,4 +1,3 @@ -//struct dd_function_table; /************************************************************************** * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. @@ -93,7 +92,10 @@ struct st_context struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS]; struct pipe_clip_state clip; - struct pipe_resource *constants[PIPE_SHADER_TYPES]; + struct { + void *ptr; + unsigned size; + } constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_scissor_state scissor; @@ -106,15 +108,6 @@ struct st_context GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */ } state; - struct { - struct st_tracked_state tracked_state[PIPE_SHADER_TYPES]; - } constants; - - /* XXX unused: */ - struct { - struct gl_fragment_program *fragment_program; - } cb; - char vendor[100]; char renderer[100]; @@ -130,7 +123,9 @@ struct st_context struct st_fragment_program *fp; /**< Currently bound fragment program */ struct st_geometry_program *gp; /**< Currently bound geometry program */ - struct st_vp_varient *vp_varient; + struct st_vp_variant *vp_variant; + struct st_fp_variant *fp_variant; + struct st_gp_variant *gp_variant; struct gl_texture_object *default_texture; @@ -160,7 +155,7 @@ struct st_context /** for glDraw/CopyPixels */ struct { - struct st_fragment_program *shaders[4]; + struct gl_fragment_program *shaders[4]; void *vert_shaders[2]; /**< ureg shaders */ } drawpix; @@ -190,6 +185,11 @@ struct st_context int force_msaa; void *winsys_drawable_handle; + + /* User vertex buffers. */ + struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS]; + unsigned user_vb_stride[PIPE_MAX_ATTRIBS]; + unsigned num_user_vbs; }; diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index df32491d04..e1e373d07d 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -89,8 +89,8 @@ st_print_current(void) } #endif - if (st->vp->varients) - tgsi_dump( st->vp->varients[0].tgsi.tokens, 0 ); + if (st->vp->variants) + tgsi_dump( st->vp->variants[0].tgsi.tokens, 0 ); if (st->vp->Base.Base.Parameters) _mesa_print_parameter_list(st->vp->Base.Base.Parameters); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 61a0e1b087..40afa43629 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -43,6 +43,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "program/prog_uniform.h" #include "vbo/vbo.h" @@ -241,15 +242,14 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, */ static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, - const struct gl_client_array **arrays, - GLboolean *userSpace) + const struct st_vp_variant *vpv, + const struct gl_client_array **arrays) { GLuint attr; const struct gl_buffer_object *firstBufObj = NULL; GLint firstStride = -1; - GLuint num_client_arrays = 0; const GLubyte *client_addr = NULL; + GLboolean user_memory; for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -258,16 +258,19 @@ is_interleaved_arrays(const struct st_vertex_program *vp, if (firstStride < 0) { firstStride = stride; + user_memory = !bufObj || !bufObj->Name; } else if (firstStride != stride) { return GL_FALSE; } - + if (!bufObj || !bufObj->Name) { - num_client_arrays++; /* Try to detect if the client-space arrays are * "close" to each other. */ + if (!user_memory) { + return GL_FALSE; + } if (!client_addr) { client_addr = arrays[mesaAttr]->Ptr; } @@ -277,6 +280,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } else if (!firstBufObj) { + if (user_memory) { + return GL_FALSE; + } firstBufObj = bufObj; } else if (bufObj != firstBufObj) { @@ -284,57 +290,11 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } - *userSpace = (num_client_arrays == vpv->num_inputs); - /* debug_printf("user space: %s (%d arrays, %d inputs)\n", - (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */ - return GL_TRUE; } /** - * Compute the memory range occupied by the arrays. - */ -static void -get_arrays_bounds(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, - const struct gl_client_array **arrays, - GLuint max_index, - const GLubyte **low, const GLubyte **high) -{ - const GLubyte *low_addr = NULL; - const GLubyte *high_addr = NULL; - GLuint attr; - - /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */ - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const GLint stride = arrays[mesaAttr]->StrideB; - const GLubyte *start = arrays[mesaAttr]->Ptr; - const unsigned sz = (arrays[mesaAttr]->Size * - _mesa_sizeof_type(arrays[mesaAttr]->Type)); - const GLubyte *end = start + (max_index * stride) + sz; - - /* debug_printf("attr %u: stride %d size %u start %p end %p\n", - attr, stride, sz, start, end); */ - - if (attr == 0) { - low_addr = start; - high_addr = end; - } - else { - low_addr = MIN2(low_addr, start); - high_addr = MAX2(high_addr, end); - } - } - - *low = low_addr; - *high = high_addr; -} - - -/** * Set up for drawing interleaved arrays that all live in one VBO * or all live in user space. * \param vbuffer returns vertex buffer info @@ -343,17 +303,27 @@ get_arrays_bounds(const struct st_vertex_program *vp, static void setup_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean userSpace, struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index, + unsigned num_instances) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; GLuint attr; - const GLubyte *offset0 = NULL; + const GLubyte *low_addr = NULL; + + /* Find the lowest address. */ + if(vpv->num_inputs) { + low_addr = arrays[vp->index_to_input[0]]->Ptr; + + for (attr = 1; attr < vpv->num_inputs; attr++) { + const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; + low_addr = MIN2(low_addr, start); + } + } for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -361,34 +331,31 @@ setup_interleaved_attribs(struct gl_context *ctx, struct st_buffer_object *stobj = st_buffer_object(bufobj); GLsizei stride = arrays[mesaAttr]->StrideB; - /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ - if (attr == 0) { - const GLubyte *low, *high; - - get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); - /* debug_printf("buffer range: %p %p range %d max index %u\n", - low, high, high - low, max_index); */ - - offset0 = low; - if (userSpace) { + 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; + uint length = (divisor ? num_instances / divisor : max_index) + 1; vbuffer->buffer = - pipe_user_buffer_create(pipe->screen, (void *) low, high - low, + pipe_user_buffer_create(pipe->screen, (void*)low_addr, + stride * length, PIPE_BIND_VERTEX_BUFFER); vbuffer->buffer_offset = 0; - } - else { - vbuffer->buffer = NULL; - pipe_resource_reference(&vbuffer->buffer, stobj->buffer); - vbuffer->buffer_offset = pointer_to_offset(low); + + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[0], vbuffer->buffer); + st->user_vb_stride[0] = stride; + st->num_user_vbs = 1; } vbuffer->stride = stride; /* in bytes */ - vbuffer->max_index = max_index; } velements[attr].src_offset = - (unsigned) (arrays[mesaAttr]->Ptr - offset0); - velements[attr].instance_divisor = 0; + (unsigned) (arrays[mesaAttr]->Ptr - low_addr); + velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; velements[attr].vertex_buffer_index = 0; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, @@ -409,12 +376,12 @@ setup_interleaved_attribs(struct gl_context *ctx, static void setup_non_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean *userSpace, struct pipe_vertex_buffer vbuffer[], - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index, + unsigned num_instances) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; @@ -425,8 +392,6 @@ setup_non_interleaved_attribs(struct gl_context *ctx, struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; GLsizei stride = arrays[mesaAttr]->StrideB; - *userSpace = GL_FALSE; - if (bufobj && bufobj->Name) { /* Attribute data is in a VBO. * Recall that for VBOs, the gl_client_array->Ptr field is @@ -434,39 +399,26 @@ setup_non_interleaved_attribs(struct gl_context *ctx, */ struct st_buffer_object *stobj = st_buffer_object(bufobj); assert(stobj->buffer); - /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ vbuffer[attr].buffer = NULL; pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer); vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); - velements[attr].src_offset = 0; } else { - /* attribute data is in user-space memory, not a VBO */ - uint bytes; - /*printf("user-space array %d stride %d\n", attr, stride);*/ - - *userSpace = GL_TRUE; - /* wrap user data */ if (arrays[mesaAttr]->Ptr) { - /* user's vertex array */ - if (arrays[mesaAttr]->StrideB) { - bytes = arrays[mesaAttr]->StrideB * (max_index + 1); - } - else { - bytes = arrays[mesaAttr]->Size - * _mesa_sizeof_type(arrays[mesaAttr]->Type); - } - vbuffer[attr].buffer = + 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, bytes, + (void *) arrays[mesaAttr]->Ptr, + stride * length, PIPE_BIND_VERTEX_BUFFER); } else { /* no array, use ctx->Current.Attrib[] value */ - bytes = sizeof(ctx->Current.Attrib[0]); - vbuffer[attr].buffer = + uint bytes = sizeof(ctx->Current.Attrib[0]); + vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, (void *) ctx->Current.Attrib[mesaAttr], bytes, @@ -475,15 +427,18 @@ setup_non_interleaved_attribs(struct gl_context *ctx, } vbuffer[attr].buffer_offset = 0; - velements[attr].src_offset = 0; - } - assert(velements[attr].src_offset <= 2048); /* 11-bit field */ + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[attr], vbuffer[attr].buffer); + st->user_vb_stride[attr] = stride; + st->num_user_vbs = MAX2(st->num_user_vbs, attr+1); + } /* common-case setup */ vbuffer[attr].stride = stride; /* in bytes */ - vbuffer[attr].max_index = max_index; - velements[attr].instance_divisor = 0; + + velements[attr].src_offset = 0; + velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; velements[attr].vertex_buffer_index = attr; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, @@ -598,6 +553,64 @@ translate_prim(const struct gl_context *ctx, unsigned prim) } +static void +st_validate_varrays(struct gl_context *ctx, + const struct gl_client_array **arrays, + unsigned max_index, + unsigned num_instances) +{ + struct st_context *st = st_context(ctx); + const struct st_vertex_program *vp; + const struct st_vp_variant *vpv; + struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; + unsigned num_vbuffers, num_velements; + GLuint attr; + unsigned i; + + /* must get these after state validation! */ + vp = st->vp; + vpv = st->vp_variant; + + memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); + + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); + } + st->num_user_vbs = 0; + + /* + * Setup the vbuffer[] and velements[] arrays. + */ + if (is_interleaved_arrays(vp, vpv, arrays)) { + setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements, + max_index, num_instances); + + num_vbuffers = 1; + num_velements = vpv->num_inputs; + if (num_velements == 0) + num_vbuffers = 0; + } + else { + setup_non_interleaved_attribs(ctx, vp, vpv, arrays, + vbuffer, velements, max_index, num_instances); + num_vbuffers = vpv->num_inputs; + num_velements = vpv->num_inputs; + } + + cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); + cso_set_vertex_elements(st->cso_context, num_velements, velements); + + /* unreference buffers (frees wrapped user-space buffer objects) + * This is OK, because the pipe driver should reference buffers by itself + * in set_vertex_buffers. */ + for (attr = 0; attr < num_vbuffers; attr++) { + pipe_resource_reference(&vbuffer[attr].buffer, NULL); + assert(!vbuffer[attr].buffer); + } +} + /** * This function gets plugged into the VBO module and is called when @@ -616,90 +629,84 @@ st_draw_vbo(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - const struct st_vertex_program *vp; - const struct st_vp_varient *vpv; - struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; - GLuint attr; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers, num_velements; struct pipe_index_buffer ibuffer; - GLboolean userSpace = GL_FALSE; - GLboolean vertDataEdgeFlags; struct pipe_draw_info info; - unsigned i; + unsigned i, num_instances = 1; + GLboolean new_array = + st->dirty.st && (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); - /* Gallium probably doesn't want this in some cases. */ - if (!index_bounds_valid) - if (!vbo_all_varyings_in_vbos(arrays)) - vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); - - /* sanity check for pointer arithmetic below */ - assert(sizeof(arrays[0]->Ptr[0]) == 1); + if (ib) { + /* Gallium probably doesn't want this in some cases. */ + if (!index_bounds_valid) + if (!vbo_all_varyings_in_vbos(arrays)) + vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); - vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && - arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; - if (vertDataEdgeFlags != st->vertdata_edgeflags) { - st->vertdata_edgeflags = vertDataEdgeFlags; - st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; + for (i = 0; i < nr_prims; i++) { + num_instances = MAX2(num_instances, prims[i].num_instances); + } + } else { + /* Get min/max index for non-indexed drawing. */ + min_index = ~0; + max_index = 0; + + for (i = 0; i < nr_prims; i++) { + min_index = MIN2(min_index, prims[i].start); + max_index = MAX2(max_index, prims[i].start + prims[i].count - 1); + num_instances = MAX2(num_instances, prims[i].num_instances); + } } - st_validate_state(st); + /* Validate state. */ + if (st->dirty.st) { + GLboolean vertDataEdgeFlags; - /* must get these after state validation! */ - vp = st->vp; - vpv = st->vp_varient; + /* sanity check for pointer arithmetic below */ + assert(sizeof(arrays[0]->Ptr[0]) == 1); + + vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && + arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; + if (vertDataEdgeFlags != st->vertdata_edgeflags) { + st->vertdata_edgeflags = vertDataEdgeFlags; + st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; + } + + st_validate_state(st); + + if (new_array) { + st_validate_varrays(ctx, arrays, max_index, num_instances); + } #if 0 - if (MESA_VERBOSE & VERBOSE_GLSL) { - check_uniforms(ctx); - } + if (MESA_VERBOSE & VERBOSE_GLSL) { + check_uniforms(ctx); + } #else - (void) check_uniforms; + (void) check_uniforms; #endif - - memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); - /* - * Setup the vbuffer[] and velements[] arrays. - */ - if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { - /*printf("Draw interleaved\n");*/ - setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, - vbuffer, velements); - num_vbuffers = 1; - num_velements = vpv->num_inputs; - if (num_velements == 0) - num_vbuffers = 0; - } - else { - /*printf("Draw non-interleaved\n");*/ - setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, - &userSpace, vbuffer, velements); - num_vbuffers = vpv->num_inputs; - num_velements = vpv->num_inputs; } -#if 0 - { - GLuint i; - for (i = 0; i < num_vbuffers; i++) { - printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); - printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); - printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); - printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); - } - for (i = 0; i < num_velements; i++) { - printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); - printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); - printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); + /* Notify the driver that the content of user buffers may have been + * changed. */ + if (!new_array && st->num_user_vbs) { + for (i = 0; i < st->num_user_vbs; i++) { + if (st->user_vb[i]) { + unsigned stride = st->user_vb_stride[i]; + + if (stride) { + pipe->redefine_user_buffer(pipe, st->user_vb[i], + min_index * stride, + (max_index + 1 - min_index) * stride); + } else { + /* stride == 0 */ + pipe->redefine_user_buffer(pipe, st->user_vb[i], + 0, st->user_vb[i]->width0); + } + } } } -#endif - - pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); - cso_set_vertex_elements(st->cso_context, num_velements, velements); setup_index_buffer(ctx, ib, &ibuffer); pipe->set_index_buffer(pipe, &ibuffer); @@ -733,17 +740,6 @@ st_draw_vbo(struct gl_context *ctx, } pipe_resource_reference(&ibuffer.buffer, NULL); - - /* unreference buffers (frees wrapped user-space buffer objects) */ - for (attr = 0; attr < num_vbuffers; attr++) { - pipe_resource_reference(&vbuffer[attr].buffer, NULL); - assert(!vbuffer[attr].buffer); - } - - if (userSpace) - { - pipe->set_vertex_buffers(pipe, 0, NULL); - } } diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h index 2e4c468cff..5d3c278228 100644 --- a/src/mesa/state_tracker/st_draw.h +++ b/src/mesa/state_tracker/st_draw.h @@ -36,10 +36,11 @@ #include "main/compiler.h" #include "main/glheader.h" -#include "main/mtypes.h" struct _mesa_index_buffer; struct _mesa_prim; +struct gl_client_array; +struct gl_context; struct st_context; void st_init_draw( struct st_context *st ); diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 7f392fc491..1e1220bfe5 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -28,6 +28,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "vbo/vbo.h" @@ -109,9 +110,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, struct pipe_index_buffer ibuffer; struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; struct pipe_transfer *ib_transfer = NULL; - struct pipe_transfer *cb_transfer; GLuint attr, i; - ubyte *mapped_constants; const void *mapped_indices = NULL; assert(draw); @@ -123,10 +122,10 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* must get these after state validation! */ vp = st->vp; - vs = &st->vp_varient->tgsi; + vs = &st->vp_variant->tgsi; - if (!st->vp_varient->draw_shader) { - st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs); + if (!st->vp_variant->draw_shader) { + st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs); } /* @@ -139,7 +138,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_viewport_state(draw, &st->state.viewport); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL); - draw_bind_vertex_shader(draw, st->vp_varient->draw_shader); + draw_bind_vertex_shader(draw, st->vp_variant->draw_shader); set_feedback_vertex_format(ctx); /* loop over TGSI shader inputs to determine vertex buffer @@ -180,7 +179,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* common-case setup */ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */ - vbuffers[attr].max_index = max_index; velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = attr; velements[attr].src_format = @@ -221,7 +219,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, break; default: assert(0); - return; + goto out_unref_vertex; } if (bufobj && bufobj->Name) { @@ -242,14 +240,10 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_mapped_index_buffer(draw, mapped_indices); } - /* map constant buffers */ - mapped_constants = pipe_buffer_map(pipe, - st->state.constants[PIPE_SHADER_VERTEX], - PIPE_TRANSFER_READ, - &cb_transfer); + /* set the constant buffer */ draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0, - mapped_constants, - st->state.constants[PIPE_SHADER_VERTEX]->width0); + st->state.constants[PIPE_SHADER_VERTEX].ptr, + st->state.constants[PIPE_SHADER_VERTEX].size); /* draw here */ @@ -258,30 +252,25 @@ st_feedback_draw_vbo(struct gl_context *ctx, } - /* unmap constant buffers */ - pipe_buffer_unmap(pipe, st->state.constants[PIPE_SHADER_VERTEX], - cb_transfer); - /* * unmap vertex/index buffers */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, draw->pt.vertex_buffer[i].buffer, - vb_transfer[i]); - pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (ib) { draw_set_mapped_index_buffer(draw, NULL); draw_set_index_buffer(draw, NULL); if (ib_transfer) - pipe_buffer_unmap(pipe, ibuffer.buffer, ib_transfer); + pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } + + out_unref_vertex: + for (attr = 0; attr < vp->num_inputs; attr++) { + pipe_buffer_unmap(pipe, vb_transfer[attr]); + draw_set_mapped_vertex_buffer(draw, attr, NULL); + pipe_resource_reference(&vbuffers[attr].buffer, NULL); + } + draw_set_vertex_buffers(draw, 0, NULL); } #endif /* FEATURE_feedback || FEATURE_rastpos */ diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 930b60ade2..bbcae3b02e 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -29,6 +29,7 @@ #include "main/imports.h" #include "main/context.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -224,6 +225,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; + ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; ctx->Extensions.ARB_multisample = GL_TRUE; ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */ @@ -258,6 +260,8 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; + if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2) + ctx->Extensions.EXT_texture_format_BGRA8888 = GL_TRUE; ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; @@ -343,6 +347,7 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) { ctx->Extensions.ARB_occlusion_query = GL_TRUE; + ctx->Extensions.ARB_occlusion_query2 = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY)) { ctx->Extensions.EXT_timer_query = GL_TRUE; @@ -361,59 +366,109 @@ void st_init_extensions(struct st_context *st) */ if (screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL, 0) && + PIPE_BIND_DEPTH_STENCIL) && screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE; } else if (screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL, 0) && + PIPE_BIND_DEPTH_STENCIL) && screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE; } /* sRGB support */ if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0) || + PIPE_BIND_SAMPLER_VIEW) || screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { ctx->Extensions.EXT_texture_sRGB = GL_TRUE; + ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; + if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET) || + screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)) { + ctx->Extensions.EXT_framebuffer_sRGB = GL_TRUE; + ctx->Const.sRGBCapable = GL_TRUE; + } } if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { ctx->Extensions.ARB_texture_rg = GL_TRUE; } /* s3tc support */ if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0) && - (ctx->Mesa_DXTn || - screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, 0))) { + PIPE_BIND_SAMPLER_VIEW) && + ctx->Mesa_DXTn) { ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; ctx->Extensions.S3_s3tc = GL_TRUE; } + if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) + ) { + ctx->Extensions.ARB_texture_compression_rgtc = GL_TRUE; + } + + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC1_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_LATC1_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_LATC2_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_LATC2_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { + ctx->Extensions.EXT_texture_compression_latc = GL_TRUE; + } + + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC2_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { + ctx->Extensions.ATI_texture_compression_3dc = GL_TRUE; + } + /* ycbcr support */ if (screen->is_format_supported(screen, PIPE_FORMAT_UYVY, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0) || + PIPE_BIND_SAMPLER_VIEW) || screen->is_format_supported(screen, PIPE_FORMAT_YUYV, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, 0)) { + PIPE_BIND_SAMPLER_VIEW)) { ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; } + /* GL_EXT_texture_array */ + if (screen->get_param(screen, PIPE_CAP_ARRAY_TEXTURES)) { + ctx->Extensions.EXT_texture_array = GL_TRUE; + ctx->Extensions.MESA_texture_array = GL_TRUE; + } + /* GL_ARB_framebuffer_object */ if (ctx->Extensions.EXT_packed_depth_stencil) { /* we support always support GL_EXT_framebuffer_blit */ @@ -428,21 +483,21 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_draw_buffers2 = GL_TRUE; } + if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_FUNC)) { + ctx->Extensions.ARB_draw_buffers_blend = GL_TRUE; + } + /* GL_ARB_half_float_vertex */ if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_FLOAT, PIPE_BUFFER, 0, - PIPE_BIND_VERTEX_BUFFER, 0)) { + PIPE_BIND_VERTEX_BUFFER)) { ctx->Extensions.ARB_half_float_vertex = GL_TRUE; } -#if 0 /* not yet */ - if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_FUNC)) { - ctx->Extensions.ARB_draw_buffers_blend = GL_TRUE; - } -#endif - if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { +#if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */ ctx->Extensions.ARB_geometry_shader4 = GL_TRUE; +#endif } if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { @@ -456,4 +511,19 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) { ctx->Extensions.ARB_shader_stencil_export = GL_TRUE; } + + if (screen->get_param(screen, PIPE_CAP_TGSI_INSTANCEID)) { + ctx->Extensions.ARB_draw_instanced = GL_TRUE; + } + if (screen->get_param(screen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR)) { + ctx->Extensions.ARB_instanced_arrays = GL_TRUE; + } + + if (screen->fence_finish) { + ctx->Extensions.ARB_sync = GL_TRUE; + } + + if (st->pipe->texture_barrier) { + ctx->Extensions.NV_texture_barrier = GL_TRUE; + } } diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index 955d821a65..03655ee048 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -37,6 +37,7 @@ #include "main/texstore.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -112,12 +113,9 @@ st_format_datatype(enum pipe_format format) return GL_UNSIGNED_SHORT; } else { - /* compressed format? */ - assert(0); + /* probably a compressed format, unsupported anyway */ + return GL_NONE; } - - assert(0); - return GL_NONE; } @@ -146,14 +144,28 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) return PIPE_FORMAT_B4G4R4A4_UNORM; case MESA_FORMAT_RGB565: return PIPE_FORMAT_B5G6R5_UNORM; + case MESA_FORMAT_RGB332: + return PIPE_FORMAT_B2G3R3_UNORM; + case MESA_FORMAT_ARGB2101010: + return PIPE_FORMAT_B10G10R10A2_UNORM; + case MESA_FORMAT_AL44: + return PIPE_FORMAT_L4A4_UNORM; case MESA_FORMAT_AL88: return PIPE_FORMAT_L8A8_UNORM; + case MESA_FORMAT_AL1616: + return PIPE_FORMAT_L16A16_UNORM; case MESA_FORMAT_A8: return PIPE_FORMAT_A8_UNORM; + case MESA_FORMAT_A16: + return PIPE_FORMAT_A16_UNORM; case MESA_FORMAT_L8: return PIPE_FORMAT_L8_UNORM; + case MESA_FORMAT_L16: + return PIPE_FORMAT_L16_UNORM; case MESA_FORMAT_I8: return PIPE_FORMAT_I8_UNORM; + case MESA_FORMAT_I16: + return PIPE_FORMAT_I16_UNORM; case MESA_FORMAT_Z16: return PIPE_FORMAT_Z16_UNORM; case MESA_FORMAT_Z32: @@ -229,6 +241,24 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) case MESA_FORMAT_RGBA_UINT32: return PIPE_FORMAT_R32G32B32A32_USCALED; + case MESA_FORMAT_RED_RGTC1: + return PIPE_FORMAT_RGTC1_UNORM; + case MESA_FORMAT_SIGNED_RED_RGTC1: + return PIPE_FORMAT_RGTC1_SNORM; + case MESA_FORMAT_RG_RGTC2: + return PIPE_FORMAT_RGTC2_UNORM; + case MESA_FORMAT_SIGNED_RG_RGTC2: + return PIPE_FORMAT_RGTC2_SNORM; + + case MESA_FORMAT_L_LATC1: + return PIPE_FORMAT_LATC1_UNORM; + case MESA_FORMAT_SIGNED_L_LATC1: + return PIPE_FORMAT_LATC1_SNORM; + case MESA_FORMAT_LA_LATC2: + return PIPE_FORMAT_LATC2_UNORM; + case MESA_FORMAT_SIGNED_LA_LATC2: + return PIPE_FORMAT_LATC2_SNORM; + default: assert(0); return PIPE_FORMAT_NONE; @@ -261,14 +291,28 @@ st_pipe_format_to_mesa_format(enum pipe_format format) return MESA_FORMAT_ARGB4444; case PIPE_FORMAT_B5G6R5_UNORM: return MESA_FORMAT_RGB565; + case PIPE_FORMAT_B2G3R3_UNORM: + return MESA_FORMAT_RGB332; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return MESA_FORMAT_ARGB2101010; + case PIPE_FORMAT_L4A4_UNORM: + return MESA_FORMAT_AL44; case PIPE_FORMAT_L8A8_UNORM: return MESA_FORMAT_AL88; + case PIPE_FORMAT_L16A16_UNORM: + return MESA_FORMAT_AL1616; case PIPE_FORMAT_A8_UNORM: return MESA_FORMAT_A8; + case PIPE_FORMAT_A16_UNORM: + return MESA_FORMAT_A16; case PIPE_FORMAT_L8_UNORM: return MESA_FORMAT_L8; + case PIPE_FORMAT_L16_UNORM: + return MESA_FORMAT_L16; case PIPE_FORMAT_I8_UNORM: return MESA_FORMAT_I8; + case PIPE_FORMAT_I16_UNORM: + return MESA_FORMAT_I16; case PIPE_FORMAT_S8_USCALED: return MESA_FORMAT_S8; @@ -354,6 +398,24 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_R32G32B32A32_USCALED: return MESA_FORMAT_RGBA_UINT32; + case PIPE_FORMAT_RGTC1_UNORM: + return MESA_FORMAT_RED_RGTC1; + case PIPE_FORMAT_RGTC1_SNORM: + return MESA_FORMAT_SIGNED_RED_RGTC1; + case PIPE_FORMAT_RGTC2_UNORM: + return MESA_FORMAT_RG_RGTC2; + case PIPE_FORMAT_RGTC2_SNORM: + return MESA_FORMAT_SIGNED_RG_RGTC2; + + case PIPE_FORMAT_LATC1_UNORM: + return MESA_FORMAT_L_LATC1; + case PIPE_FORMAT_LATC1_SNORM: + return MESA_FORMAT_SIGNED_L_LATC1; + case PIPE_FORMAT_LATC2_UNORM: + return MESA_FORMAT_LA_LATC2; + case PIPE_FORMAT_LATC2_SNORM: + return MESA_FORMAT_SIGNED_LA_LATC2; + default: assert(0); return MESA_FORMAT_NONE; @@ -370,13 +432,12 @@ find_supported_format(struct pipe_screen *screen, uint num_formats, enum pipe_texture_target target, unsigned sample_count, - unsigned tex_usage, - unsigned geom_flags) + unsigned tex_usage) { uint i; for (i = 0; i < num_formats; i++) { if (screen->is_format_supported(screen, formats[i], target, - sample_count, tex_usage, geom_flags)) { + sample_count, tex_usage)) { return formats[i]; } } @@ -391,8 +452,7 @@ static enum pipe_format default_rgba_format(struct pipe_screen *screen, enum pipe_texture_target target, unsigned sample_count, - unsigned tex_usage, - unsigned geom_flags) + unsigned tex_usage) { static const enum pipe_format colorFormats[] = { PIPE_FORMAT_B8G8R8A8_UNORM, @@ -401,7 +461,7 @@ default_rgba_format(struct pipe_screen *screen, PIPE_FORMAT_B5G6R5_UNORM }; return find_supported_format(screen, colorFormats, Elements(colorFormats), - target, sample_count, tex_usage, geom_flags); + target, sample_count, tex_usage); } @@ -412,8 +472,7 @@ static enum pipe_format default_rgb_format(struct pipe_screen *screen, enum pipe_texture_target target, unsigned sample_count, - unsigned tex_usage, - unsigned geom_flags) + unsigned tex_usage) { static const enum pipe_format colorFormats[] = { PIPE_FORMAT_B8G8R8X8_UNORM, @@ -425,7 +484,7 @@ default_rgb_format(struct pipe_screen *screen, PIPE_FORMAT_B5G6R5_UNORM }; return find_supported_format(screen, colorFormats, Elements(colorFormats), - target, sample_count, tex_usage, geom_flags); + target, sample_count, tex_usage); } /** @@ -435,8 +494,7 @@ static enum pipe_format default_srgba_format(struct pipe_screen *screen, enum pipe_texture_target target, unsigned sample_count, - unsigned tex_usage, - unsigned geom_flags) + unsigned tex_usage) { static const enum pipe_format colorFormats[] = { PIPE_FORMAT_B8G8R8A8_SRGB, @@ -444,7 +502,7 @@ default_srgba_format(struct pipe_screen *screen, PIPE_FORMAT_A8B8G8R8_SRGB, }; return find_supported_format(screen, colorFormats, Elements(colorFormats), - target, sample_count, tex_usage, geom_flags); + target, sample_count, tex_usage); } @@ -466,170 +524,180 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, enum pipe_texture_target target, unsigned sample_count, unsigned bindings) { - unsigned geom_flags = 0; /* we don't care about POT vs. NPOT here, yet */ switch (internalFormat) { + case GL_RGB10: + case GL_RGB10_A2: + if (screen->is_format_supported( screen, PIPE_FORMAT_B10G10R10A2_UNORM, + target, sample_count, bindings)) + return PIPE_FORMAT_B10G10R10A2_UNORM; + /* Pass through. */ case 4: case GL_RGBA: case GL_RGBA8: - case GL_RGB10_A2: - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + + case GL_BGRA: + if (screen->is_format_supported( screen, PIPE_FORMAT_B8G8R8A8_UNORM, + target, sample_count, bindings)) + return PIPE_FORMAT_B8G8R8A8_UNORM; + return default_rgba_format( screen, target, sample_count, bindings); case 3: case GL_RGB: - return default_rgb_format( screen, target, sample_count, bindings, - geom_flags ); + case GL_RGB8: + return default_rgb_format( screen, target, sample_count, bindings); + + case GL_RGB12: + case GL_RGB16: case GL_RGBA12: case GL_RGBA16: if (screen->is_format_supported( screen, PIPE_FORMAT_R16G16B16A16_UNORM, - target, sample_count, bindings, - geom_flags )) + target, sample_count, bindings)) return PIPE_FORMAT_R16G16B16A16_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); case GL_RGBA4: case GL_RGBA2: if (screen->is_format_supported( screen, PIPE_FORMAT_B4G4R4A4_UNORM, - target, sample_count, bindings, - geom_flags )) + target, sample_count, bindings)) return PIPE_FORMAT_B4G4R4A4_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); case GL_RGB5_A1: if (screen->is_format_supported( screen, PIPE_FORMAT_B5G5R5A1_UNORM, - target, sample_count, bindings, - geom_flags )) + target, sample_count, bindings)) return PIPE_FORMAT_B5G5R5A1_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); - - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return default_rgb_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + case GL_R3_G3_B2: + if (screen->is_format_supported( screen, PIPE_FORMAT_B2G3R3_UNORM, + target, sample_count, bindings)) + return PIPE_FORMAT_B2G3R3_UNORM; + /* Pass through. */ case GL_RGB5: case GL_RGB4: - case GL_R3_G3_B2: if (screen->is_format_supported( screen, PIPE_FORMAT_B5G6R5_UNORM, - target, sample_count, bindings, - geom_flags )) + target, sample_count, bindings)) return PIPE_FORMAT_B5G6R5_UNORM; if (screen->is_format_supported( screen, PIPE_FORMAT_B5G5R5A1_UNORM, - target, sample_count, bindings, - geom_flags )) + target, sample_count, bindings)) return PIPE_FORMAT_B5G5R5A1_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + case GL_ALPHA12: + case GL_ALPHA16: + if (screen->is_format_supported( screen, PIPE_FORMAT_A16_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_A16_UNORM; + /* Pass through. */ case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: case GL_COMPRESSED_ALPHA: if (screen->is_format_supported( screen, PIPE_FORMAT_A8_UNORM, target, - sample_count, bindings, geom_flags )) + sample_count, bindings)) return PIPE_FORMAT_A8_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + case GL_LUMINANCE12: + case GL_LUMINANCE16: + if (screen->is_format_supported( screen, PIPE_FORMAT_L16_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_L16_UNORM; + /* Pass through. */ case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case GL_COMPRESSED_LUMINANCE: if (screen->is_format_supported( screen, PIPE_FORMAT_L8_UNORM, target, - sample_count, bindings, geom_flags )) + sample_count, bindings)) return PIPE_FORMAT_L8_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + if (screen->is_format_supported( screen, PIPE_FORMAT_L16A16_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_L16A16_UNORM; + /* Pass through. */ case 2: case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - case GL_COMPRESSED_LUMINANCE_ALPHA: if (screen->is_format_supported( screen, PIPE_FORMAT_L8A8_UNORM, target, - sample_count, bindings, geom_flags )) + sample_count, bindings)) + return PIPE_FORMAT_L8A8_UNORM; + return default_rgba_format( screen, target, sample_count, bindings); + + case GL_LUMINANCE4_ALPHA4: + if (screen->is_format_supported( screen, PIPE_FORMAT_L4A4_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_L4A4_UNORM; + if (screen->is_format_supported( screen, PIPE_FORMAT_L8A8_UNORM, target, + sample_count, bindings)) return PIPE_FORMAT_L8A8_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); + case GL_INTENSITY12: + case GL_INTENSITY16: + if (screen->is_format_supported( screen, PIPE_FORMAT_I16_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_I16_UNORM; + /* Pass through. */ case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: case GL_COMPRESSED_INTENSITY: if (screen->is_format_supported( screen, PIPE_FORMAT_I8_UNORM, target, - sample_count, bindings, geom_flags )) + sample_count, bindings)) return PIPE_FORMAT_I8_UNORM; - return default_rgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_rgba_format( screen, target, sample_count, bindings); case GL_YCBCR_MESA: if (screen->is_format_supported(screen, PIPE_FORMAT_UYVY, target, - sample_count, bindings, geom_flags)) { + sample_count, bindings)) { return PIPE_FORMAT_UYVY; } if (screen->is_format_supported(screen, PIPE_FORMAT_YUYV, target, - sample_count, bindings, geom_flags)) { + sample_count, bindings)) { return PIPE_FORMAT_YUYV; } return PIPE_FORMAT_NONE; - case GL_COMPRESSED_RED: - case GL_COMPRESSED_RG: case GL_COMPRESSED_RGB: /* can only sample from compressed formats */ if (bindings & ~PIPE_BIND_SAMPLER_VIEW) return PIPE_FORMAT_NONE; else if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGB, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT1_RGB; else - return default_rgb_format(screen, target, sample_count, bindings, - geom_flags); + return default_rgb_format(screen, target, sample_count, bindings); case GL_COMPRESSED_RGBA: /* can only sample from compressed formats */ if (bindings & ~PIPE_BIND_SAMPLER_VIEW) return PIPE_FORMAT_NONE; else if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_RGBA, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT3_RGBA; else - return default_rgba_format(screen, target, sample_count, bindings, - geom_flags); + return default_rgba_format(screen, target, sample_count, bindings); case GL_RGB_S3TC: case GL_RGB4_S3TC: case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGB, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT1_RGB; else return PIPE_FORMAT_NONE; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGBA, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT1_RGBA; else return PIPE_FORMAT_NONE; @@ -638,16 +706,14 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_RGBA4_S3TC: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_RGBA, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT3_RGBA; else return PIPE_FORMAT_NONE; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, - target, sample_count, bindings, - geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_DXT5_RGBA; else return PIPE_FORMAT_NONE; @@ -661,32 +727,32 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_DEPTH_COMPONENT16: if (screen->is_format_supported(screen, PIPE_FORMAT_Z16_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_Z16_UNORM; /* fall-through */ case GL_DEPTH_COMPONENT24: if (screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED, - target, sample_count, bindings, geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_Z24_UNORM_S8_USCALED; if (screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM, - target, sample_count, bindings, geom_flags)) + target, sample_count, bindings)) return PIPE_FORMAT_S8_USCALED_Z24_UNORM; /* fall-through */ case GL_DEPTH_COMPONENT32: if (screen->is_format_supported(screen, PIPE_FORMAT_Z32_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_Z32_UNORM; /* fall-through */ case GL_DEPTH_COMPONENT: { static const enum pipe_format formats[] = { - PIPE_FORMAT_Z16_UNORM, PIPE_FORMAT_Z32_UNORM, PIPE_FORMAT_Z24_UNORM_S8_USCALED, - PIPE_FORMAT_S8_USCALED_Z24_UNORM + PIPE_FORMAT_S8_USCALED_Z24_UNORM, + PIPE_FORMAT_Z16_UNORM }; return find_supported_format(screen, formats, Elements(formats), - target, sample_count, bindings, geom_flags); + target, sample_count, bindings); } case GL_STENCIL_INDEX: @@ -701,7 +767,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, PIPE_FORMAT_S8_USCALED_Z24_UNORM }; return find_supported_format(screen, formats, Elements(formats), - target, sample_count, bindings, geom_flags); + target, sample_count, bindings); } case GL_DEPTH_STENCIL_EXT: @@ -712,23 +778,32 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, PIPE_FORMAT_S8_USCALED_Z24_UNORM }; return find_supported_format(screen, formats, Elements(formats), - target, sample_count, bindings, geom_flags); + target, sample_count, bindings); } case GL_SRGB_EXT: case GL_SRGB8_EXT: - case GL_COMPRESSED_SRGB_EXT: - case GL_COMPRESSED_SRGB_ALPHA_EXT: case GL_SRGB_ALPHA_EXT: case GL_SRGB8_ALPHA8_EXT: - return default_srgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_srgba_format( screen, target, sample_count, bindings); + + case GL_COMPRESSED_SRGB_EXT: case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - return PIPE_FORMAT_DXT1_SRGB; + if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_SRGB, target, + sample_count, bindings)) + return PIPE_FORMAT_DXT1_SRGB; + return default_srgba_format( screen, target, sample_count, bindings); + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return PIPE_FORMAT_DXT1_SRGBA; + + case GL_COMPRESSED_SRGB_ALPHA_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - return PIPE_FORMAT_DXT3_SRGBA; + if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_SRGBA, target, + sample_count, bindings)) + return PIPE_FORMAT_DXT3_SRGBA; + return default_srgba_format( screen, target, sample_count, bindings); + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return PIPE_FORMAT_DXT5_SRGBA; @@ -737,68 +812,107 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_COMPRESSED_SLUMINANCE_EXT: case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_L8A8_SRGB, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_L8A8_SRGB; - return default_srgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_srgba_format( screen, target, sample_count, bindings); case GL_SLUMINANCE_EXT: case GL_SLUMINANCE8_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_L8_SRGB, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_L8_SRGB; - return default_srgba_format( screen, target, sample_count, bindings, - geom_flags ); + return default_srgba_format( screen, target, sample_count, bindings); case GL_RED: case GL_R8: if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R8_UNORM; return PIPE_FORMAT_NONE; case GL_RG: case GL_RG8: if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R8G8_UNORM; return PIPE_FORMAT_NONE; case GL_R16: if (screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R16_UNORM; return PIPE_FORMAT_NONE; case GL_RG16: if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R16G16_UNORM; return PIPE_FORMAT_NONE; + case GL_COMPRESSED_RED: case GL_COMPRESSED_RED_RGTC1: if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_RGTC1_UNORM; + if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_R8_UNORM; return PIPE_FORMAT_NONE; case GL_COMPRESSED_SIGNED_RED_RGTC1: if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_SNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_RGTC1_SNORM; return PIPE_FORMAT_NONE; + case GL_COMPRESSED_RG: case GL_COMPRESSED_RG_RGTC2: if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_UNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_RGTC2_UNORM; + if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_R8G8_UNORM; return PIPE_FORMAT_NONE; case GL_COMPRESSED_SIGNED_RG_RGTC2: if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_SNORM, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_RGTC2_SNORM; return PIPE_FORMAT_NONE; + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC1_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_LATC1_UNORM; + if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_L8_UNORM; + return PIPE_FORMAT_NONE; + + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC1_SNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_LATC1_SNORM; + return PIPE_FORMAT_NONE; + + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC2_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_LATC2_UNORM; + if (screen->is_format_supported(screen, PIPE_FORMAT_L8A8_UNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_L8A8_UNORM; + return PIPE_FORMAT_NONE; + + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + if (screen->is_format_supported(screen, PIPE_FORMAT_LATC2_SNORM, target, + sample_count, bindings)) + return PIPE_FORMAT_LATC2_SNORM; + return PIPE_FORMAT_NONE; + /* signed/unsigned integer formats. * XXX Mesa only has formats for RGBA signed/unsigned integer formats. * If/when new formats are added this code should be updated. @@ -822,7 +936,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_LUMINANCE_ALPHA8I_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_SSCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R8G8B8A8_SSCALED; return PIPE_FORMAT_NONE; case GL_RGBA16I_EXT: @@ -833,7 +947,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_LUMINANCE_ALPHA16I_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_SSCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R16G16B16A16_SSCALED; return PIPE_FORMAT_NONE; case GL_RGBA32I_EXT: @@ -845,7 +959,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, /* xxx */ if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_SSCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R32G32B32A32_SSCALED; return PIPE_FORMAT_NONE; @@ -857,7 +971,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_LUMINANCE_ALPHA8UI_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_USCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R8G8B8A8_USCALED; return PIPE_FORMAT_NONE; @@ -869,7 +983,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_LUMINANCE_ALPHA16UI_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_USCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R16G16B16A16_USCALED; return PIPE_FORMAT_NONE; @@ -881,7 +995,7 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_LUMINANCE_ALPHA32UI_EXT: if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_USCALED, target, - sample_count, bindings, geom_flags)) + sample_count, bindings)) return PIPE_FORMAT_R32G32B32A32_USCALED; return PIPE_FORMAT_NONE; @@ -955,8 +1069,14 @@ gl_format st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat, GLenum format, GLenum type) { + boolean want_renderable = + internalFormat == 3 || internalFormat == 4 || + internalFormat == GL_RGB || internalFormat == GL_RGBA || + internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 || + internalFormat == GL_BGRA; + return st_ChooseTextureFormat_renderable(ctx, internalFormat, - format, type, GL_TRUE); + format, type, want_renderable); } /** @@ -1010,3 +1130,55 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2) return GL_FALSE; } + + + +/** + * This is used for translating texture border color and the clear + * color. For example, the clear color is interpreted according to + * the renderbuffer's base format. For example, if clearing a + * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] = + * alpha. Similarly for texture border colors. + */ +void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]) +{ + switch (baseFormat) { + case GL_RED: + colorOut[0] = colorIn[0]; + colorOut[1] = 0.0F; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RG: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RGB: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = colorIn[2]; + colorOut[3] = 1.0F; + break; + case GL_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = 0.0; + colorOut[3] = colorIn[3]; + break; + case GL_LUMINANCE: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = 1.0; + break; + case GL_LUMINANCE_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = colorIn[3]; + break; + case GL_INTENSITY: + colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; + break; + default: + COPY_4V(colorOut, colorIn); + } +} diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index 43fa59b100..0fb570f6ee 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -31,11 +31,12 @@ #define ST_FORMAT_H #include "main/formats.h" -#include "main/mtypes.h" +#include "main/glheader.h" #include "pipe/p_defines.h" #include "pipe/p_format.h" +struct gl_context; struct pipe_screen; extern GLenum @@ -76,4 +77,10 @@ st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type); extern GLboolean st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2); + +extern void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]); + + #endif /* ST_FORMAT_H */ diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index c5f6008a22..aea69c1b43 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -87,7 +87,7 @@ st_render_mipmap(struct st_context *st, /* XXX should probably kill this and always use util_gen_mipmap since this implements a sw fallback as well */ if (!screen->is_format_supported(screen, psv->format, psv->texture->target, - 0, PIPE_BIND_RENDER_TARGET, 0)) { + 0, PIPE_BIND_RENDER_TARGET)) { return FALSE; } @@ -103,54 +103,78 @@ st_render_mipmap(struct st_context *st, * image with stride==width. */ static void -decompress_image(enum pipe_format format, - const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) +decompress_image(enum pipe_format format, int datatype, + const uint8_t *src, void *dst, + unsigned width, unsigned height, unsigned src_stride) { const struct util_format_description *desc = util_format_description(format); const uint bw = util_format_get_blockwidth(format); const uint bh = util_format_get_blockheight(format); - const uint dst_stride = 4 * MAX2(width, bw); - const uint src_stride = util_format_get_stride(format, width); - - desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); - - if (width < bw || height < bh) { - /* We're decompressing an image smaller than the compression - * block size. We don't want garbage pixel values in the region - * outside (width x height) so replicate pixels from the (width - * x height) region to fill out the (bw x bh) block size. - */ - uint x, y; - for (y = 0; y < bh; y++) { - for (x = 0; x < bw; x++) { - if (x >= width || y >= height) { - uint p = (y * bw + x) * 4; - dst[p + 0] = dst[0]; - dst[p + 1] = dst[1]; - dst[p + 2] = dst[2]; - dst[p + 3] = dst[3]; - } - } + uint dst_stride = 4 * MAX2(width, bw); + + if (datatype == GL_FLOAT) { + desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height); + if (width < bw || height < bh) { + float *dst_p = (float *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } + } + } else { + desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height); + if (width < bw || height < bh) { + uint8_t *dst_p = (uint8_t *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } } } } - /** * Helper function to compress an image. The source is a 32-bpp RGBA image * with stride==width. */ static void -compress_image(enum pipe_format format, - const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) +compress_image(enum pipe_format format, int datatype, + const void *src, uint8_t *dst, + unsigned width, unsigned height, unsigned dst_stride) { const struct util_format_description *desc = util_format_description(format); - const uint dst_stride = util_format_get_stride(format, width); const uint src_stride = 4 * width; - desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); + if (datatype == GL_FLOAT) + desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height); + else + desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height); } @@ -180,7 +204,10 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); if (compressed) { - datatype = GL_UNSIGNED_BYTE; + GLenum type = + _mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat); + + datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT; comps = 4; } else { @@ -232,11 +259,11 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, assert(comps == 4); - srcTemp = malloc(srcWidth2 * srcHeight2 * comps + 000); - dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000); + srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); + dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); /* decompress the src image: srcData -> srcTemp */ - decompress_image(format, srcData, srcTemp, srcWidth, srcHeight); + decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride); _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, @@ -248,7 +275,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstWidth2); /* stride in texels */ /* compress the new image: dstTemp -> dstData */ - compress_image(format, dstTemp, dstData, dstWidth, dstHeight); + compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride); free(srcTemp); free(dstTemp); @@ -338,6 +365,11 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, if (lastLevel == 0) return; + /* The texture isn't in a "complete" state yet so set the expected + * lastLevel here, since it won't get done in st_finalize_texture(). + */ + stObj->lastLevel = lastLevel; + if (pt->last_level < lastLevel) { /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. @@ -352,13 +384,9 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, oldTex->width0, oldTex->height0, oldTex->depth0, + oldTex->array_size, oldTex->bind); - /* The texture isn't in a "complete" state yet so set the expected - * lastLevel here, since it won't get done in st_finalize_texture(). - */ - stObj->lastLevel = lastLevel; - /* This will copy the old texture's base image into the new texture * which we just allocated. */ @@ -367,8 +395,6 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); pipe_sampler_view_reference(&stObj->sampler_view, NULL); - - pt = stObj->pt; } else { /* Make sure that the base texture image data is present in the @@ -377,6 +403,8 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, st_finalize_texture(ctx, st->pipe, texObj); } + pt = stObj->pt; + assert(pt->last_level >= lastLevel); /* Try to generate the mipmap by rendering/texturing. If that fails, diff --git a/src/mesa/state_tracker/st_gen_mipmap.h b/src/mesa/state_tracker/st_gen_mipmap.h index 3ba091da15..815c6a5163 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.h +++ b/src/mesa/state_tracker/st_gen_mipmap.h @@ -30,8 +30,10 @@ #define ST_GEN_MIPMAP_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; +struct gl_texture_object; struct st_context; extern void diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 0307b48978..a68544ddac 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -38,6 +38,7 @@ #include "main/mtypes.h" #include "main/context.h" +#include "main/mfeatures.h" #include "main/texobj.h" #include "main/teximage.h" #include "main/texstate.h" @@ -425,19 +426,13 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi) struct gl_config mode; gl_buffer_index idx; + if (!stfbi) + return NULL; + stfb = CALLOC_STRUCT(st_framebuffer); if (!stfb) return NULL; - /* for FBO-only context */ - if (!stfbi) { - struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer(); - - stfb->Base = *base; - - return stfb; - } - st_visual_to_context_mode(stfbi->visual, &mode); _mesa_initialize_window_framebuffer(&stfb->Base, &mode); @@ -507,13 +502,14 @@ 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_flush(st, fence); + if (flags & ST_FLUSH_FRONT) st_manager_flush_frontbuffer(st); } static boolean -st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, +st_context_teximage(struct st_context_iface *stctxi, + enum st_texture_type target, int level, enum pipe_format internal_format, struct pipe_resource *tex, boolean mipmap) { @@ -688,8 +684,9 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, if (attribs->major > 1 || attribs->minor > 0) { _mesa_compute_version(st->ctx); - if (st->ctx->VersionMajor < attribs->major || - st->ctx->VersionMajor < attribs->minor) { + /* is the actual version less than the requested version? */ + if (st->ctx->VersionMajor * 10 + st->ctx->VersionMinor < + attribs->major * 10 + attribs->minor) { st_destroy_context(st); return NULL; } @@ -762,7 +759,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); } else { - ret = FALSE; + struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); + ret = _mesa_make_current(st->ctx, incomplete, incomplete); } st_framebuffer_reference(&stdraw, NULL); @@ -865,7 +863,8 @@ st_manager_validate_framebuffers(struct st_context *st) * Add a color renderbuffer on demand. */ boolean -st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb, +st_manager_add_color_renderbuffer(struct st_context *st, + struct gl_framebuffer *fb, gl_buffer_index idx) { struct st_framebuffer *stfb = st_ws_framebuffer(fb); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index f848462310..c07739f9d5 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -72,6 +72,7 @@ struct st_translate { struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst address[1]; struct ureg_src samplers[PIPE_MAX_SAMPLERS]; + struct ureg_src systemValues[SYSTEM_VALUE_MAX]; /* Extra info for handling point size clamping in vertex shader */ struct ureg_dst pointSizeResult; /**< Actual point size output register */ @@ -104,6 +105,13 @@ struct st_translate { }; +/** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */ +static unsigned mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { + TGSI_SEMANTIC_FACE, + TGSI_SEMANTIC_INSTANCEID +}; + + /** * Make note of a branch to a label in the TGSI code. * After we've emitted all instructions, we'll go over the list @@ -216,9 +224,9 @@ src_register( struct st_translate *t, case PROGRAM_TEMPORARY: assert(index >= 0); + assert(index < Elements(t->temps)); if (ureg_dst_is_undef(t->temps[index])) t->temps[index] = ureg_DECL_temporary( t->ureg ); - assert(index < Elements(t->temps)); return ureg_src(t->temps[index]); case PROGRAM_NAMED_PARAM: @@ -245,6 +253,10 @@ src_register( struct st_translate *t, case PROGRAM_ADDRESS: return ureg_src(t->address[index]); + case PROGRAM_SYSTEM_VALUE: + assert(index < Elements(t->systemValues)); + return t->systemValues[index]; + default: debug_assert( 0 ); return ureg_src_undef(); @@ -274,6 +286,8 @@ translate_texture_target( GLuint textarget, case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; default: debug_assert( 0 ); return TGSI_TEXTURE_1D; @@ -739,10 +753,12 @@ compile_instruction( /** * Emit the TGSI instructions to adjust the WPOS pixel center convention + * Basically, add (adjX, adjY) to the fragment position. */ static void emit_adjusted_wpos( struct st_translate *t, - const struct gl_program *program, GLfloat value) + const struct gl_program *program, + GLfloat adjX, GLfloat adjY) { struct ureg_program *ureg = t->ureg; struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg); @@ -752,7 +768,7 @@ emit_adjusted_wpos( struct st_translate *t, * The shader might also use gl_FragCoord.w and .z. */ ureg_ADD(ureg, wpos_temp, wpos_input, - ureg_imm4f(ureg, value, value, 0.0f, 0.0f)); + ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f)); t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp); } @@ -836,9 +852,12 @@ emit_wpos(struct st_context *st, boolean invert = FALSE; if (fp->OriginUpperLeft) { + /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { + /* the driver supports upper-left origin */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) { + /* the driver supports lower-left origin, need to invert Y */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); invert = TRUE; } @@ -846,28 +865,37 @@ emit_wpos(struct st_context *st, assert(0); } else { + /* Fragment shader wants origin in lower-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) + /* the driver supports lower-left origin */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) + /* the driver supports upper-left origin, need to invert Y */ invert = TRUE; else assert(0); } if (fp->PixelCenterInteger) { + /* Fragment shader wants pixel center integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) + /* the driver supports pixel center integer */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) - emit_adjusted_wpos(t, program, invert ? 0.5f : -0.5f); + /* the driver supports pixel center half integer, need to bias X,Y */ + emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f); else assert(0); } else { + /* Fragment shader wants pixel center half integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) { + /* the driver supports pixel center half integer */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { + /* the driver supports pixel center integer, need to bias X,Y */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - emit_adjusted_wpos(t, program, invert ? -0.5f : 0.5f); + emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f); } else assert(0); @@ -1089,6 +1117,21 @@ st_translate_mesa_program( t->address[0] = ureg_DECL_address( ureg ); } + /* Declare misc input registers + */ + { + GLbitfield sysInputs = program->SystemValuesRead; + unsigned numSys = 0; + for (i = 0; sysInputs; i++) { + if (sysInputs & (1 << i)) { + unsigned semName = mesa_sysval_to_semantic[i]; + t->systemValues[i] = ureg_DECL_system_value(ureg, numSys, semName, 0); + numSys++; + sysInputs &= ~(1 << i); + } + } + } + if (program->IndirectRegisterFiles & (1 << PROGRAM_TEMPORARY)) { /* If temps are accessed with indirect addressing, declare temporaries * in sequential order. Else, we declare them on demand elsewhere. diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h index 9bfd4960b6..0615e52ef6 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.h +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h @@ -29,18 +29,20 @@ #ifndef ST_MESA_TO_TGSI_H #define ST_MESA_TO_TGSI_H -#include "main/mtypes.h" - -#include "pipe/p_compiler.h" - -struct ureg_program; - #if defined __cplusplus extern "C" { #endif -struct tgsi_token; +#include "main/glheader.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_defines.h" + +struct gl_context; struct gl_program; +struct tgsi_token; +struct ureg_program; + enum pipe_error st_translate_mesa_program( diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index aae2913c20..0b1ad63afe 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -32,7 +32,10 @@ #include "main/imports.h" +#include "main/hash.h" +#include "main/mfeatures.h" #include "main/mtypes.h" +#include "program/prog_parameter.h" #include "program/prog_print.h" #include "program/programopt.h" @@ -44,6 +47,8 @@ #include "tgsi/tgsi_ureg.h" #include "st_debug.h" +#include "st_cb_bitmap.h" +#include "st_cb_drawpixels.h" #include "st_context.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" @@ -52,34 +57,111 @@ /** + * Delete a vertex program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) +{ + if (vpv->driver_shader) + cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); + +#if FEATURE_feedback || FEATURE_rastpos + if (vpv->draw_shader) + draw_delete_vertex_shader( st->draw, vpv->draw_shader ); +#endif + + if (vpv->tgsi.tokens) + st_free_tokens(vpv->tgsi.tokens); + + FREE( vpv ); +} + + + +/** * Clean out any old compilations: */ void -st_vp_release_varients( struct st_context *st, +st_release_vp_variants( struct st_context *st, struct st_vertex_program *stvp ) { - struct st_vp_varient *vpv; + struct st_vp_variant *vpv; - for (vpv = stvp->varients; vpv; ) { - struct st_vp_varient *next = vpv->next; + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + delete_vp_variant(st, vpv); + vpv = next; + } - if (vpv->driver_shader) - cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); - -#if FEATURE_feedback || FEATURE_rastpos - if (vpv->draw_shader) - draw_delete_vertex_shader( st->draw, vpv->draw_shader ); -#endif + stvp->variants = NULL; +} + + + +/** + * Delete a fragment program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) +{ + if (fpv->driver_shader) + cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); + if (fpv->parameters) + _mesa_free_parameter_list(fpv->parameters); - if (vpv->tgsi.tokens) - st_free_tokens(vpv->tgsi.tokens); + FREE(fpv); +} + + +/** + * Free all variants of a fragment program. + */ +void +st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp) +{ + struct st_fp_variant *fpv; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + delete_fp_variant(st, fpv); + fpv = next; + } + + stfp->variants = NULL; +} + + +/** + * Delete a geometry program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv) +{ + if (gpv->driver_shader) + cso_delete_geometry_shader(st->cso_context, gpv->driver_shader); - FREE( vpv ); + FREE(gpv); +} - vpv = next; + +/** + * Free all variants of a geometry program. + */ +void +st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp) +{ + struct st_gp_variant *gpv; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + delete_gp_variant(st, gpv); + gpv = next; } - stvp->varients = NULL; + stgp->variants = NULL; } @@ -92,7 +174,7 @@ st_vp_release_varients( struct st_context *st, * \param tokensOut destination for TGSI tokens * \return pointer to cached pipe_shader object. */ -void +static void st_prepare_vertex_program(struct st_context *st, struct st_vertex_program *stvp) { @@ -196,17 +278,22 @@ st_prepare_vertex_program(struct st_context *st, } -struct st_vp_varient * +/** + * Translate a vertex program to create a new variant. + */ +static struct st_vp_variant * st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, - const struct st_vp_varient_key *key) + const struct st_vp_variant_key *key) { - struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); + struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant); struct pipe_context *pipe = st->pipe; struct ureg_program *ureg; enum pipe_error error; unsigned num_outputs; + st_prepare_vertex_program( st, stvp ); + _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); @@ -231,23 +318,22 @@ st_translate_vertex_program(struct st_context *st, debug_printf("\n"); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_VERTEX, - ureg, - &stvp->Base.Base, - /* inputs */ - vpv->num_inputs, - stvp->input_to_index, - NULL, /* input semantic name */ - NULL, /* input semantic index */ - NULL, - /* outputs */ - num_outputs, - stvp->result_to_output, - stvp->output_semantic_name, - stvp->output_semantic_index, - key->passthrough_edgeflags ); + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_VERTEX, + ureg, + &stvp->Base.Base, + /* inputs */ + vpv->num_inputs, + stvp->input_to_index, + NULL, /* input semantic name */ + NULL, /* input semantic index */ + NULL, + /* outputs */ + num_outputs, + stvp->result_to_output, + stvp->output_semantic_name, + stvp->output_semantic_index, + key->passthrough_edgeflags ); if (error) goto fail; @@ -277,201 +363,326 @@ fail: } +/** + * Find/create a vertex program variant. + */ +struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key) +{ + struct st_vp_variant *vpv; + + /* Search for existing variant */ + for (vpv = stvp->variants; vpv; vpv = vpv->next) { + if (memcmp(&vpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!vpv) { + /* create now */ + vpv = st_translate_vertex_program(st, stvp, key); + if (vpv) { + /* insert into list */ + vpv->next = stvp->variants; + stvp->variants = vpv; + } + } + + return vpv; +} + /** - * Translate a Mesa fragment shader into a TGSI shader. - * \return pointer to cached pipe_shader object. + * Translate a Mesa fragment shader into a TGSI shader using extra info in + * the key. + * \return new fragment program variant */ -void +static struct st_fp_variant * st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *stfp ) + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) { struct pipe_context *pipe = st->pipe; - GLuint outputMapping[FRAG_RESULT_MAX]; - GLuint inputMapping[FRAG_ATTRIB_MAX]; - GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ - GLuint attr; - enum pipe_error error; - const GLbitfield inputsRead = stfp->Base.Base.InputsRead; - struct ureg_program *ureg; + struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); + GLboolean deleteFP = GL_FALSE; - ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; - uint fs_num_inputs = 0; + if (!variant) + return NULL; - ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; - ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; - uint fs_num_outputs = 0; + assert(!(key->bitmap && key->drawpixels)); - _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); +#if FEATURE_drawpix + if (key->bitmap) { + /* glBitmap drawing */ + struct gl_fragment_program *fp; /* we free this temp program below */ - /* - * Convert Mesa program inputs to TGSI input register semantics. - */ - for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { - if (inputsRead & (1 << attr)) { - const GLuint slot = fs_num_inputs++; + st_make_bitmap_fragment_program(st, &stfp->Base, + &fp, &variant->bitmap_sampler); - inputMapping[attr] = slot; + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + stfp = st_fragment_program(fp); + deleteFP = GL_TRUE; + } + else if (key->drawpixels) { + /* glDrawPixels drawing */ + struct gl_fragment_program *fp; /* we free this temp program below */ - switch (attr) { - case FRAG_ATTRIB_WPOS: - input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL0: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL1: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 1; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_FOGC: - input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - case FRAG_ATTRIB_FACE: - input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; - break; - /* In most cases, there is nothing special about these - * inputs, so adopt a convention to use the generic - * semantic name and the mesa FRAG_ATTRIB_ number as the - * index. - * - * All that is required is that the vertex shader labels - * its own outputs similarly, and that the vertex shader - * generates at least every output required by the - * fragment shader plus fixed-function hardware (such as - * BFC). - * - * There is no requirement that semantic indexes start at - * zero or be restricted to a particular range -- nobody - * should be building tables based on semantic index. - */ - case FRAG_ATTRIB_PNTC: - case FRAG_ATTRIB_TEX0: - case FRAG_ATTRIB_TEX1: - case FRAG_ATTRIB_TEX2: - case FRAG_ATTRIB_TEX3: - case FRAG_ATTRIB_TEX4: - case FRAG_ATTRIB_TEX5: - case FRAG_ATTRIB_TEX6: - case FRAG_ATTRIB_TEX7: - case FRAG_ATTRIB_VAR0: - default: - /* Actually, let's try and zero-base this just for - * readability of the generated TGSI. - */ - assert(attr >= FRAG_ATTRIB_TEX0); - input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); - input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - if (attr == FRAG_ATTRIB_PNTC) - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - else - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - } + if (key->drawpixels_z || key->drawpixels_stencil) { + fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, + key->drawpixels_stencil); } else { - inputMapping[attr] = -1; + /* RGBA */ + st_make_drawpix_fragment_program(st, &stfp->Base, &fp); + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + deleteFP = GL_TRUE; } + stfp = st_fragment_program(fp); } +#endif - /* - * Semantics and mapping for outputs - */ - { - uint numColors = 0; - GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; - - /* if z is written, emit that first */ - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); - } + if (!stfp->tgsi.tokens) { + /* need to translate Mesa instructions to TGSI now */ + GLuint outputMapping[FRAG_RESULT_MAX]; + GLuint inputMapping[FRAG_ATTRIB_MAX]; + GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ + GLuint attr; + enum pipe_error error; + const GLbitfield inputsRead = stfp->Base.Base.InputsRead; + struct ureg_program *ureg; + GLboolean write_all = GL_FALSE; - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); - } + ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + uint fs_num_inputs = 0; + + ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; + ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; + uint fs_num_outputs = 0; + + + _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + + /* + * Convert Mesa program inputs to TGSI input register semantics. + */ + for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { + if (inputsRead & (1 << attr)) { + const GLuint slot = fs_num_inputs++; + + inputMapping[attr] = slot; - /* handle remaning outputs (color) */ - for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { - if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { - case FRAG_RESULT_DEPTH: - case FRAG_RESULT_STENCIL: - /* handled above */ - assert(0); + case FRAG_ATTRIB_WPOS: + input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_COL0: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; + case FRAG_ATTRIB_COL1: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 1; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_FOGC: + input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + case FRAG_ATTRIB_FACE: + input_semantic_name[slot] = TGSI_SEMANTIC_FACE; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; + /* In most cases, there is nothing special about these + * inputs, so adopt a convention to use the generic + * semantic name and the mesa FRAG_ATTRIB_ number as the + * index. + * + * All that is required is that the vertex shader labels + * its own outputs similarly, and that the vertex shader + * generates at least every output required by the + * fragment shader plus fixed-function hardware (such as + * BFC). + * + * There is no requirement that semantic indexes start at + * zero or be restricted to a particular range -- nobody + * should be building tables based on semantic index. + */ + case FRAG_ATTRIB_PNTC: + case FRAG_ATTRIB_TEX0: + case FRAG_ATTRIB_TEX1: + case FRAG_ATTRIB_TEX2: + case FRAG_ATTRIB_TEX3: + case FRAG_ATTRIB_TEX4: + case FRAG_ATTRIB_TEX5: + case FRAG_ATTRIB_TEX6: + case FRAG_ATTRIB_TEX7: + case FRAG_ATTRIB_VAR0: default: - assert(attr == FRAG_RESULT_COLOR || - (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; - fs_output_semantic_index[fs_num_outputs] = numColors; - outputMapping[attr] = fs_num_outputs; - numColors++; + /* Actually, let's try and zero-base this just for + * readability of the generated TGSI. + */ + assert(attr >= FRAG_ATTRIB_TEX0); + input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); + input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + if (attr == FRAG_ATTRIB_PNTC) + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + else + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; } + } + else { + inputMapping[attr] = -1; + } + } + /* + * Semantics and mapping for outputs + */ + { + uint numColors = 0; + GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; + + /* if z is written, emit that first */ + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); + } + + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; + fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); + } + + /* handle remaning outputs (color) */ + for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { + if (outputsWritten & BITFIELD64_BIT(attr)) { + switch (attr) { + case FRAG_RESULT_DEPTH: + case FRAG_RESULT_STENCIL: + /* handled above */ + assert(0); + break; + case FRAG_RESULT_COLOR: + write_all = GL_TRUE; /* fallthrough */ + default: + assert(attr == FRAG_RESULT_COLOR || + (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; + fs_output_semantic_index[fs_num_outputs] = numColors; + outputMapping[attr] = fs_num_outputs; + numColors++; + break; + } + + fs_num_outputs++; + } } } - } - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (ureg == NULL) - return; + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; - if (ST_DEBUG & DEBUG_MESA) { - _mesa_print_program(&stfp->Base.Base); - _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); - debug_printf("\n"); + if (ST_DEBUG & DEBUG_MESA) { + _mesa_print_program(&stfp->Base.Base); + _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); + debug_printf("\n"); + } + if (write_all == GL_TRUE) + ureg_property_fs_color0_writes_all_cbufs(ureg, 1); + + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_FRAGMENT, + ureg, + &stfp->Base.Base, + /* inputs */ + fs_num_inputs, + inputMapping, + input_semantic_name, + input_semantic_index, + interpMode, + /* outputs */ + fs_num_outputs, + outputMapping, + fs_output_semantic_name, + fs_output_semantic_index, FALSE ); + + stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); + ureg_destroy( ureg ); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_FRAGMENT, - ureg, - &stfp->Base.Base, - /* inputs */ - fs_num_inputs, - inputMapping, - input_semantic_name, - input_semantic_index, - interpMode, - /* outputs */ - fs_num_outputs, - outputMapping, - fs_output_semantic_name, - fs_output_semantic_index, FALSE ); - - stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); - ureg_destroy( ureg ); - stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + /* fill in variant */ + variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + variant->key = *key; if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); debug_printf("\n"); } + + if (deleteFP) { + /* Free the temporary program made above */ + struct gl_fragment_program *fp = &stfp->Base; + _mesa_reference_fragprog(st->ctx, &fp, NULL); + } + + return variant; } -void + +/** + * Translate fragment program if needed. + */ +struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) +{ + struct st_fp_variant *fpv; + + /* Search for existing variant */ + for (fpv = stfp->variants; fpv; fpv = fpv->next) { + if (memcmp(&fpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!fpv) { + /* create new */ + fpv = st_translate_fragment_program(st, stfp, key); + if (fpv) { + /* insert into list */ + fpv->next = stfp->variants; + stfp->variants = fpv; + } + } + + return fpv; +} + + +/** + * Translate a geometry program to create a new variant. + */ +static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp) + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) { GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint outputMapping[GEOM_RESULT_MAX]; @@ -494,12 +705,19 @@ st_translate_geometry_program(struct st_context *st, GLuint maxSlot = 0; struct ureg_program *ureg; + struct st_gp_variant *gpv; + + gpv = CALLOC_STRUCT(st_gp_variant); + if (!gpv) + return NULL; + _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { - return; + FREE(gpv); + return NULL; } /* which vertex output goes to the first geometry input */ @@ -529,7 +747,7 @@ st_translate_geometry_program(struct st_context *st, } else ++gs_builtin_inputs; -#if 1 +#if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif @@ -580,7 +798,7 @@ st_translate_geometry_program(struct st_context *st, * mapping and the semantic information for each output. */ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { - if (stgp->Base.Base.OutputsWritten & (1 << attr)) { + if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot; slot = gs_num_outputs; @@ -671,37 +889,35 @@ st_translate_geometry_program(struct st_context *st, st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); - error = st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_GEOMETRY, - ureg, - &stgp->Base.Base, - /* inputs */ - gs_num_inputs, - inputMapping, - stgp->input_semantic_name, - stgp->input_semantic_index, - NULL, - /* outputs */ - gs_num_outputs, - outputMapping, - gs_output_semantic_name, - gs_output_semantic_index, - FALSE); - + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_GEOMETRY, + ureg, + &stgp->Base.Base, + /* inputs */ + gs_num_inputs, + inputMapping, + stgp->input_semantic_name, + stgp->input_semantic_index, + NULL, + /* outputs */ + gs_num_outputs, + outputMapping, + gs_output_semantic_name, + gs_output_semantic_index, + FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); - stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + + /* fill in new variant */ + gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + gpv->key = *key; if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); @@ -712,8 +928,44 @@ st_translate_geometry_program(struct st_context *st, tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } + + return gpv; } + +/** + * Get/create geometry program variant. + */ +struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) +{ + struct st_gp_variant *gpv; + + /* Search for existing variant */ + for (gpv = stgp->variants; gpv; gpv = gpv->next) { + if (memcmp(&gpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!gpv) { + /* create new */ + gpv = st_translate_geometry_program(st, stgp, key); + if (gpv) { + /* insert into list */ + gpv->next = stgp->variants; + stgp->variants = gpv; + } + } + + return gpv; +} + + + + /** * Debug- print current shader text */ @@ -759,3 +1011,155 @@ st_print_shaders(struct gl_context *ctx) } } } + + +/** + * Vert/Geom/Frag programs have per-context variants. Free all the + * variants attached to the given program which match the given context. + */ +static void +destroy_program_variants(struct st_context *st, struct gl_program *program) +{ + if (!program) + return; + + switch (program->Target) { + case GL_VERTEX_PROGRAM_ARB: + { + struct st_vertex_program *stvp = (struct st_vertex_program *) program; + struct st_vp_variant *vpv, **prevPtr = &stvp->variants; + + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + if (vpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_vp_variant(st, vpv); + } + else { + prevPtr = &vpv->next; + } + vpv = next; + } + } + break; + case GL_FRAGMENT_PROGRAM_ARB: + { + struct st_fragment_program *stfp = + (struct st_fragment_program *) program; + struct st_fp_variant *fpv, **prevPtr = &stfp->variants; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + if (fpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_fp_variant(st, fpv); + } + else { + prevPtr = &fpv->next; + } + fpv = next; + } + } + break; + case MESA_GEOMETRY_PROGRAM: + { + struct st_geometry_program *stgp = + (struct st_geometry_program *) program; + struct st_gp_variant *gpv, **prevPtr = &stgp->variants; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + if (gpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_gp_variant(st, gpv); + } + else { + prevPtr = &gpv->next; + } + gpv = next; + } + } + break; + default: + _mesa_problem(NULL, "Unexpected program target in " + "destroy_program_variants_cb()"); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the shader's program variants + * which match the given context. + */ +static void +destroy_shader_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_shader *shader = (struct gl_shader *) data; + + switch (shader->Type) { + case GL_SHADER_PROGRAM_MESA: + { + struct gl_shader_program *shProg = (struct gl_shader_program *) data; + GLuint i; + + for (i = 0; i < shProg->NumShaders; i++) { + destroy_program_variants(st, shProg->Shaders[i]->Program); + } + + destroy_program_variants(st, (struct gl_program *) + shProg->VertexProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->FragmentProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->GeometryProgram); + } + break; + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + case GL_GEOMETRY_SHADER: + { + destroy_program_variants(st, shader->Program); + } + break; + default: + assert(0); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the program variants which match + * the given context. + */ +static void +destroy_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_program *program = (struct gl_program *) data; + destroy_program_variants(st, program); +} + + +/** + * Walk over all shaders and programs to delete any variants which + * belong to the given context. + * This is called during context tear-down. + */ +void +st_destroy_program_variants(struct st_context *st) +{ + /* ARB vert/frag program */ + _mesa_HashWalk(st->ctx->Shared->Programs, + destroy_program_variants_cb, st); + + /* GLSL vert/frag/geom shaders */ + _mesa_HashWalk(st->ctx->Shared->ShaderObjects, + destroy_shader_program_variants_cb, st); +} diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 72dbc715fe..c4244df939 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -40,26 +40,61 @@ #include "st_context.h" +/** Fragment program variant key */ +struct st_fp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + + /** for glBitmap */ + GLuint bitmap:1; /**< glBitmap variant? */ + + /** for glDrawPixels */ + GLuint drawpixels:1; /**< glDrawPixels variant */ + GLuint scaleAndBias:1; /**< glDrawPixels w/ scale and/or bias? */ + GLuint pixelMaps:1; /**< glDrawPixels w/ pixel lookup map? */ + GLuint drawpixels_z:1; /**< glDrawPixels(GL_DEPTH) */ + GLuint drawpixels_stencil:1; /**< glDrawPixels(GL_STENCIL) */ +}; + + +/** + * Variant of a fragment program. + */ +struct st_fp_variant +{ + /** Parameters which generated this version of fragment program */ + struct st_fp_variant_key key; + + /** Driver's compiled shader */ + void *driver_shader; + + /** For glBitmap variants */ + struct gl_program_parameter_list *parameters; + uint bitmap_sampler; + + /** next in linked list */ + struct st_fp_variant *next; +}; + + /** * Derived from Mesa gl_fragment_program: */ struct st_fragment_program { struct gl_fragment_program Base; - GLuint serialNo; struct pipe_shader_state tgsi; - void *driver_shader; - /** Program prefixed with glBitmap prologue */ - struct st_fragment_program *bitmap_program; - uint bitmap_sampler; + struct st_fp_variant *variants; }; -struct st_vp_varient_key +/** Vertex program variant key */ +struct st_vp_variant_key { + struct st_context *st; /**< variants are per-context */ boolean passthrough_edgeflags; }; @@ -68,12 +103,12 @@ struct st_vp_varient_key * This represents a vertex program, especially translated to match * the inputs of a particular fragment shader. */ -struct st_vp_varient +struct st_vp_variant { /* Parameters which generated this translated version of a vertex * shader: */ - struct st_vp_varient_key key; + struct st_vp_variant_key key; /** * TGSI tokens (to later generate a 'draw' module shader for @@ -88,9 +123,9 @@ struct st_vp_varient struct draw_vertex_shader *draw_shader; /** Next in linked list */ - struct st_vp_varient *next; + struct st_vp_variant *next; - /** similar to that in st_vertex_program, but with information about edgeflags too */ + /** similar to that in st_vertex_program, but with edgeflags info too */ GLuint num_inputs; }; @@ -101,7 +136,6 @@ struct st_vp_varient struct st_vertex_program { struct gl_vertex_program Base; /**< The Mesa vertex program */ - GLuint serialNo, lastSerialNo; /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ GLuint input_to_index[VERT_ATTRIB_MAX]; @@ -115,18 +149,41 @@ struct st_vertex_program ubyte output_semantic_index[VERT_RESULT_MAX]; GLuint num_outputs; - /** List of translated varients of this vertex program. + /** List of translated variants of this vertex program. */ - struct st_vp_varient *varients; + struct st_vp_variant *variants; +}; + + + +/** Geometry program variant key */ +struct st_gp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + /* no other fields yet */ +}; + + +/** + * Geometry program variant. + */ +struct st_gp_variant +{ + /* Parameters which generated this translated version of a vertex */ + struct st_gp_variant_key key; + + void *driver_shader; + + struct st_gp_variant *next; }; + /** * Derived from Mesa gl_geometry_program: */ struct st_geometry_program { struct gl_geometry_program Base; /**< The Mesa geometry program */ - GLuint serialNo; /** map GP input back to VP output */ GLuint input_map[PIPE_MAX_SHADER_INPUTS]; @@ -145,9 +202,12 @@ struct st_geometry_program ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; struct pipe_shader_state tgsi; - void *driver_shader; + + struct st_gp_variant *variants; }; + + static INLINE struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) { @@ -162,9 +222,9 @@ st_vertex_program( struct gl_vertex_program *vp ) } static INLINE struct st_geometry_program * -st_geometry_program( struct gl_geometry_program *vp ) +st_geometry_program( struct gl_geometry_program *gp ) { - return (struct st_geometry_program *)vp; + return (struct st_geometry_program *)gp; } static INLINE void @@ -198,32 +258,43 @@ st_reference_fragprog(struct st_context *st, } -extern void -st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *fp); +extern struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key); + + +extern struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key); + + +extern struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key); + + extern void -st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp); +st_release_vp_variants( struct st_context *st, + struct st_vertex_program *stvp ); -/* Called after program string change, discard all previous - * compilation results. - */ extern void -st_prepare_vertex_program(struct st_context *st, - struct st_vertex_program *stvp); +st_release_fp_variants( struct st_context *st, + struct st_fragment_program *stfp ); -extern struct st_vp_varient * -st_translate_vertex_program(struct st_context *st, - struct st_vertex_program *stvp, - const struct st_vp_varient_key *key); +extern void +st_release_gp_variants(struct st_context *st, + struct st_geometry_program *stgp); -void -st_vp_release_varients( struct st_context *st, - struct st_vertex_program *stvp ); extern void st_print_shaders(struct gl_context *ctx); +extern void +st_destroy_program_variants(struct st_context *st); + #endif diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 155ea39f18..ffe7e256a5 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -59,6 +59,7 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint bind ) { struct pipe_resource pt, *newtex; @@ -68,6 +69,8 @@ st_texture_create(struct st_context *st, assert(width0 > 0); assert(height0 > 0); assert(depth0 > 0); + if (target == PIPE_TEXTURE_CUBE) + assert(layers == 6); DBG("%s target %s format %s last_level %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), @@ -75,7 +78,7 @@ st_texture_create(struct st_context *st, assert(format); assert(screen->is_format_supported(screen, format, target, 0, - PIPE_BIND_SAMPLER_VIEW, 0)); + PIPE_BIND_SAMPLER_VIEW)); memset(&pt, 0, sizeof(pt)); pt.target = target; @@ -84,7 +87,7 @@ st_texture_create(struct st_context *st, pt.width0 = width0; pt.height0 = height0; pt.depth0 = depth0; - pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1); + pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers); pt.usage = PIPE_USAGE_DEFAULT; pt.bind = bind; pt.flags = 0; @@ -98,6 +101,72 @@ st_texture_create(struct st_context *st, /** + * In OpenGL the number of 1D array texture layers is the "height" and + * the number of 2D array texture layers is the "depth". In Gallium the + * number of layers in an array texture is a separate 'array_size' field. + * This function converts dimensions from the former to the later. + */ +void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut) +{ + switch (texture) { + case GL_TEXTURE_1D: + assert(heightIn == 1); + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_1D_ARRAY: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = heightIn; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_CUBE_MAP: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 6; + break; + case GL_TEXTURE_2D_ARRAY: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = depthIn; + break; + default: + assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); + /* fall-through */ + case GL_TEXTURE_3D: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = depthIn; + *layersOut = 1; + break; + } +} + + +/** * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean @@ -105,6 +174,8 @@ st_texture_match_image(const struct pipe_resource *pt, const struct gl_texture_image *image, GLuint face, GLuint level) { + GLuint ptWidth, ptHeight, ptDepth, ptLayers; + /* Images with borders are never pulled into mipmap textures. */ if (image->Border) @@ -115,12 +186,17 @@ st_texture_match_image(const struct pipe_resource *pt, if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format) return GL_FALSE; + st_gl_texture_dims_to_pipe_dims(image->TexObject->Target, + image->Width, image->Height, image->Depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + /* Test if this image's size matches what's expected in the * established texture. */ - if (image->Width != u_minify(pt->width0, level) || - image->Height != u_minify(pt->height0, level) || - image->Depth != u_minify(pt->depth0, level)) + if (ptWidth != u_minify(pt->width0, level) || + ptHeight != u_minify(pt->height0, level) || + ptDepth != u_minify(pt->depth0, level) || + ptLayers != pt->array_size) return GL_FALSE; return GL_TRUE; @@ -212,14 +288,20 @@ st_texture_image_data(struct st_context *st, GLuint src_row_stride, GLuint src_image_stride) { struct pipe_context *pipe = st->pipe; - GLuint depth = u_minify(dst->depth0, level); GLuint i; const GLubyte *srcUB = src; struct pipe_transfer *dst_transfer; + GLuint layers; + + if (dst->target == PIPE_TEXTURE_1D_ARRAY || + dst->target == PIPE_TEXTURE_2D_ARRAY) + layers = dst->array_size; + else + layers = u_minify(dst->depth0, level); DBG("%s\n", __FUNCTION__); - for (i = 0; i < depth; i++) { + for (i = 0; i < layers; i++) { dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i, PIPE_TRANSFER_WRITE, 0, 0, u_minify(dst->width0, level), diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index c78901c036..d50c3c9af7 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -71,7 +71,10 @@ struct st_texture_object */ GLuint lastLevel; - /** The size of the level=0 mipmap image */ + /** The size of the level=0 mipmap image. + * Note that the number of 1D array layers will be in height0 and the + * number of 2D array layers will be in depth0, as in GL. + */ GLuint width0, height0, depth0; /* On validation any active images held in main memory or in other @@ -125,9 +128,7 @@ st_create_texture_sampler_view(struct pipe_context *pipe, { struct pipe_sampler_view templ; - u_sampler_view_default_template(&templ, - texture, - texture->format); + u_sampler_view_default_template(&templ, texture, texture->format); return pipe->create_sampler_view(pipe, texture, &templ); } @@ -140,17 +141,15 @@ st_create_texture_sampler_view_format(struct pipe_context *pipe, { struct pipe_sampler_view templ; - u_sampler_view_default_template(&templ, - texture, - format); + u_sampler_view_default_template(&templ, texture, format); return pipe->create_sampler_view(pipe, texture, &templ); } + static INLINE struct pipe_sampler_view * st_get_texture_sampler_view(struct st_texture_object *stObj, struct pipe_context *pipe) - { if (!stObj || !stObj->pt) { return NULL; @@ -172,9 +171,20 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint tex_usage ); +extern void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut); + /* Check if an image fits into an existing texture object. */ extern GLboolean |