static void brw_vs_populate_key(struct brw_context *brw, struct brw_vs_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(key, 0, sizeof(*key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key->program_string_id = vp->id; if (ctx->Transform.ClipPlanesEnabled != 0 && (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) && vp->program.Base.ClipDistanceArraySize == 0) { key->nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } /* _NEW_POLYGON */ if (brw->gen < 6) { key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } if (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_BFC0 | VARYING_BIT_BFC1)) { /* _NEW_LIGHT | _NEW_BUFFERS */ key->clamp_vertex_color = ctx->Light._ClampVertexColor; } /* _NEW_POINT */ if (brw->gen < 6 && ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key->point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count, &key->tex); /* BRW_NEW_VS_ATTRIB_WORKAROUNDS */ memcpy(key->gl_attrib_wa_flags, brw->vb.attrib_wa_flags, sizeof(brw->vb.attrib_wa_flags)); }
static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { radeonTexObj *t = radeon_tex_obj(texObj); GLuint firstLevel; GLuint lastLevel; int width, height, depth; int i; width = texImage->Width; height = texImage->Height; depth = texImage->Depth; if (texImage->Level > texObj->BaseLevel && (width == 1 || (texObj->Target != GL_TEXTURE_1D && height == 1) || (texObj->Target == GL_TEXTURE_3D && depth == 1))) { /* For this combination, we're at some lower mipmap level and * some important dimension is 1. We can't extrapolate up to a * likely base level width/height/depth for a full mipmap stack * from this info, so just allocate this one level. */ firstLevel = texImage->Level; lastLevel = texImage->Level; } else { if (texImage->Level < texObj->BaseLevel) firstLevel = 0; else firstLevel = texObj->BaseLevel; for (i = texImage->Level; i > firstLevel; i--) { width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; } if ((texObj->Sampler.MinFilter == GL_NEAREST || texObj->Sampler.MinFilter == GL_LINEAR) && texImage->Level == firstLevel) { lastLevel = firstLevel; } else { lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); } } return radeon_miptree_create(rmesa, texObj->Target, texImage->TexFormat, firstLevel, lastLevel - firstLevel + 1, width, height, depth, t->tile_bits); }
void brw_setup_vec4_key_clip_info(struct brw_context *brw, struct brw_vec4_prog_key *key, bool program_uses_clip_distance) { struct gl_context *ctx = &brw->ctx; key->userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); if (key->userclip_active && !program_uses_clip_distance) { key->nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } }
static GLboolean st_TestProxyTexImage(struct gl_context *ctx, GLenum target, GLint level, gl_format format, GLint width, GLint height, GLint depth, GLint border) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; if (width == 0 || height == 0 || depth == 0) { /* zero-sized images are legal, and always fit! */ return GL_TRUE; } if (pipe->screen->can_create_resource) { /* Ask the gallium driver if the texture is too large */ struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); struct pipe_resource pt; /* Setup the pipe_resource object */ memset(&pt, 0, sizeof(pt)); pt.target = gl_target_to_pipe(target); pt.format = st_mesa_format_to_pipe_format(format); st_gl_texture_dims_to_pipe_dims(target, width, height, depth, &pt.width0, &pt.height0, &pt.depth0, &pt.array_size); if (level == 0 && (texObj->Sampler.MinFilter == GL_LINEAR || texObj->Sampler.MinFilter == GL_NEAREST)) { /* assume just one mipmap level */ pt.last_level = 0; } else { /* assume a full set of mipmaps */ pt.last_level = _mesa_logbase2(MAX3(width, height, depth)); } return pipe->screen->can_create_resource(pipe->screen, &pt); } else { /* Use core Mesa fallback */ return _mesa_test_proxy_teximage(ctx, target, level, format, width, height, depth, border); } }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_clip_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_clip_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_LIGHT | _NEW_POLYGON | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_FS_PROG_DATA | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; memset(&key, 0, sizeof(key)); /* Populate the key: */ /* BRW_NEW_FS_PROG_DATA */ const struct brw_wm_prog_data *wm_prog_data = brw_wm_prog_data(brw->wm.base.prog_data); if (wm_prog_data) { key.contains_flat_varying = wm_prog_data->contains_flat_varying; key.contains_noperspective_varying = wm_prog_data->contains_noperspective_varying; STATIC_ASSERT(sizeof(key.interp_mode) == sizeof(wm_prog_data->interp_mode)); memcpy(key.interp_mode, wm_prog_data->interp_mode, sizeof(key.interp_mode)); } /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->reduced_primitive; /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* _NEW_LIGHT */ key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); /* _NEW_TRANSFORM (also part of VUE map)*/ if (ctx->Transform.ClipPlanesEnabled) key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; if (brw->gen == 5) key.clip_mode = BRW_CLIP_MODE_KERNEL_CLIP; else key.clip_mode = BRW_CLIP_MODE_NORMAL; /* _NEW_POLYGON */ if (key.primitive == GL_TRIANGLES) { if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) key.clip_mode = BRW_CLIP_MODE_REJECT_ALL; else { GLuint fill_front = BRW_CLIP_FILL_MODE_CULL; GLuint fill_back = BRW_CLIP_FILL_MODE_CULL; GLuint offset_front = 0; GLuint offset_back = 0; if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_FRONT) { switch (ctx->Polygon.FrontMode) { case GL_FILL: fill_front = BRW_CLIP_FILL_MODE_FILL; offset_front = 0; break; case GL_LINE: fill_front = BRW_CLIP_FILL_MODE_LINE; offset_front = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_front = BRW_CLIP_FILL_MODE_POINT; offset_front = ctx->Polygon.OffsetPoint; break; } } if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_BACK) { switch (ctx->Polygon.BackMode) { case GL_FILL: fill_back = BRW_CLIP_FILL_MODE_FILL; offset_back = 0; break; case GL_LINE: fill_back = BRW_CLIP_FILL_MODE_LINE; offset_back = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_back = BRW_CLIP_FILL_MODE_POINT; offset_back = ctx->Polygon.OffsetPoint; break; } } if (ctx->Polygon.BackMode != GL_FILL || ctx->Polygon.FrontMode != GL_FILL) { key.do_unfilled = 1; /* Most cases the fixed function units will handle. Cases where * one or more polygon faces are unfilled will require help: */ key.clip_mode = BRW_CLIP_MODE_CLIP_NON_REJECTED; if (offset_back || offset_front) { /* _NEW_POLYGON, _NEW_BUFFERS */ key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2; key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD; } if (!brw->polygon_front_bit) { key.fill_ccw = fill_front; key.fill_cw = fill_back; key.offset_ccw = offset_front; key.offset_cw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_cw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_cw = 1; } else { key.fill_cw = fill_front; key.fill_ccw = fill_back; key.offset_cw = offset_front; key.offset_ccw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_ccw = 1; } } } } if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG, &key, sizeof(key), &brw->clip.prog_offset, &brw->clip.prog_data)) { compile_clip_prog( brw, &key ); } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.base.program_string_id = vp->id; key.base.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.base.uses_clip_distance = vp->program.UsesClipDistance; if (key.base.userclip_active && !key.base.uses_clip_distance) { if (brw->gen < 6) { key.base.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.base.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.base.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (brw->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (brw->gen < 6 && ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.base.tex); /* BRW_NEW_VERTICES */ if (brw->gen < 8 && !brw->is_haswell) { /* Prior to Haswell, the hardware can't natively support GL_FIXED or * 2_10_10_10_REV vertex formats. Set appropriate workaround flags. */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (!(vp->program.Base.InputsRead & BITFIELD64_BIT(i))) continue; uint8_t wa_flags = 0; switch (brw->vb.inputs[i].glarray->Type) { case GL_FIXED: wa_flags = brw->vb.inputs[i].glarray->Size; break; case GL_INT_2_10_10_10_REV: wa_flags |= BRW_ATTRIB_WA_SIGN; /* fallthough */ case GL_UNSIGNED_INT_2_10_10_10_REV: if (brw->vb.inputs[i].glarray->Format == GL_BGRA) wa_flags |= BRW_ATTRIB_WA_BGRA; if (brw->vb.inputs[i].glarray->Normalized) wa_flags |= BRW_ATTRIB_WA_NORMALIZE; else if (!brw->vb.inputs[i].glarray->Integer) wa_flags |= BRW_ATTRIB_WA_SCALE; break; } key.gl_attrib_wa_flags[i] = wa_flags; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_geom_out = brw->vs.prog_data->base.vue_map; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.program_string_id = vp->id; key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.uses_clip_distance = vp->program.UsesClipDistance; if (key.userclip_active && !key.uses_clip_distance) { if (intel->gen < 6) { key.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (intel->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.tex); /* BRW_NEW_VERTICES */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (vp->program.Base.InputsRead & BITFIELD64_BIT(i) && brw->vb.inputs[i].glarray->Type == GL_FIXED) { key.gl_fixed_input_size[i] = brw->vb.inputs[i].glarray->Size; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } brw->vs.constant_map = ((int8_t *)brw->vs.prog_data + sizeof(*brw->vs.prog_data)); }
/* Work back from the specified level of the image to the baselevel and create a * miptree of that size. */ struct intel_mipmap_tree * intel_miptree_create_for_teximage(struct intel_context *intel, struct intel_texture_object *intelObj, struct intel_texture_image *intelImage, bool expect_accelerated_upload) { GLuint firstLevel; GLuint lastLevel; int width, height, depth; GLuint i; intel_miptree_get_dimensions_for_image(&intelImage->base.Base, &width, &height, &depth); DBG("%s\n", __FUNCTION__); if (intelImage->base.Base.Level > intelObj->base.BaseLevel && (width == 1 || (intelObj->base.Target != GL_TEXTURE_1D && height == 1) || (intelObj->base.Target == GL_TEXTURE_3D && depth == 1))) { /* For this combination, we're at some lower mipmap level and * some important dimension is 1. We can't extrapolate up to a * likely base level width/height/depth for a full mipmap stack * from this info, so just allocate this one level. */ firstLevel = intelImage->base.Base.Level; lastLevel = intelImage->base.Base.Level; } else { /* If this image disrespects BaseLevel, allocate from level zero. * Usually BaseLevel == 0, so it's unlikely to happen. */ if (intelImage->base.Base.Level < intelObj->base.BaseLevel) firstLevel = 0; else firstLevel = intelObj->base.BaseLevel; /* Figure out image dimensions at start level. */ for (i = intelImage->base.Base.Level; i > firstLevel; i--) { width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; } /* Guess a reasonable value for lastLevel. This is probably going * to be wrong fairly often and might mean that we have to look at * resizable buffers, or require that buffers implement lazy * pagetable arrangements. */ if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || intelObj->base.Sampler.MinFilter == GL_LINEAR) && intelImage->base.Base.Level == firstLevel && (intel->gen < 4 || firstLevel == 0)) { lastLevel = firstLevel; } else if (intelObj->base.Target == GL_TEXTURE_EXTERNAL_OES) { lastLevel = firstLevel; } else { lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); } } return intel_miptree_create(intel, intelObj->base.Target, intelImage->base.Base.TexFormat, firstLevel, lastLevel, width, height, depth, expect_accelerated_upload, 0 /* num_samples */, false /* msaa_is_interleaved */); }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { const GLboolean isProxy = _mesa_is_proxy_texture(target); struct gl_texture_object *texObj; GLuint maxDim; /* size check */ if (width < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); } return GL_TRUE; } /* levels check */ if (levels < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); } return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* check levels against maximum */ if (levels > _mesa_max_texture_levels(ctx, target)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); } return GL_TRUE; } /* check levels against width/height/depth */ maxDim = MAX3(width, height, depth); if (levels > _mesa_logbase2(maxDim) + 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); } return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || (texObj->Name == 0 && !isProxy)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); } return GL_TRUE; } /* Check if texObj->Immutable is set */ if (texObj->Immutable) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); } return GL_TRUE; } return GL_FALSE; }