/** * 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) { switch (target) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); 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); 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); return _mesa_init_geometry_program(ctx, &prog->Base, target, id); } default: assert(0); return NULL; } }
/** called via ctx->Driver.NewTextureImage() */ static struct gl_texture_image * st_NewTextureImage(struct gl_context * ctx) { DBG("%s\n", __FUNCTION__); (void) ctx; return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image); }
/** called via ctx->Driver.NewTextureObject() */ static struct gl_texture_object * st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) { struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object); DBG("%s\n", __FUNCTION__); _mesa_initialize_texture_object(&obj->base, name, target); return &obj->base; }
/** * There is some duplication between mesa's bufferobjects and our * bufmgr buffers. Both have an integer handle and a hashtable to * lookup an opaque structure. It would be nice if the handles and * internal structure where somehow shared. */ static struct gl_buffer_object * st_bufferobj_alloc(struct gl_context *ctx, GLuint name, GLenum target) { struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object); if (!st_obj) return NULL; _mesa_initialize_buffer_object(ctx, &st_obj->Base, name, target); return &st_obj->Base; }
static struct gl_query_object * st_NewQueryObject(GLcontext *ctx, GLuint id) { struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object); if (stq) { stq->base.Id = id; stq->base.Ready = GL_TRUE; stq->pq = NULL; return &stq->base; } return NULL; }
/** * 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) { switch (target) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } case GL_FRAGMENT_PROGRAM_ARB: { struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } case GL_TESS_CONTROL_PROGRAM_NV: { struct st_tessctrl_program *prog = ST_CALLOC_STRUCT(st_tessctrl_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } case GL_TESS_EVALUATION_PROGRAM_NV: { struct st_tesseval_program *prog = ST_CALLOC_STRUCT(st_tesseval_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } case GL_COMPUTE_PROGRAM_NV: { struct st_compute_program *prog = ST_CALLOC_STRUCT(st_compute_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } default: assert(0); return NULL; } }
static struct gl_query_object * st_NewQueryObject(struct gl_context *ctx, GLuint id) { struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object); if (stq) { stq->base.Id = id; stq->base.Ready = GL_TRUE; stq->pq = NULL; stq->type = PIPE_QUERY_TYPES; /* an invalid value */ return &stq->base; } return NULL; }
/** * Called via ctx->Driver.NewRenderbuffer() */ static struct gl_renderbuffer * st_new_renderbuffer(struct gl_context *ctx, GLuint name) { struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer); if (strb) { assert(name != 0); _mesa_init_renderbuffer(&strb->Base, name); strb->Base.Delete = st_renderbuffer_delete; strb->Base.AllocStorage = st_renderbuffer_alloc_storage; return &strb->Base; } return NULL; }
/** Per-context init */ void st_init_bitmap(struct st_context *st) { struct pipe_sampler_state *sampler = &st->bitmap.samplers[0]; struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; /* init sampler state once */ memset(sampler, 0, sizeof(*sampler)); sampler->wrap_s = PIPE_TEX_WRAP_CLAMP; sampler->wrap_t = PIPE_TEX_WRAP_CLAMP; sampler->wrap_r = PIPE_TEX_WRAP_CLAMP; sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST; sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE; sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST; st->bitmap.samplers[1] = *sampler; st->bitmap.samplers[1].normalized_coords = 1; /* init baseline rasterizer state once */ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); st->bitmap.rasterizer.half_pixel_center = 1; st->bitmap.rasterizer.bottom_edge_rule = 1; st->bitmap.rasterizer.depth_clip = 1; /* find a usable texture format */ 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)) { 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)) { st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; } else { /* XXX support more formats */ assert(0); } /* alloc bitmap cache object */ st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache); reset_cache(st); }
/** * Create GL selection mode drawing stage. */ static struct draw_stage * draw_glselect_stage(struct gl_context *ctx, struct draw_context *draw) { struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage); fs->stage.draw = draw; fs->stage.next = NULL; fs->stage.point = select_point; fs->stage.line = select_line; fs->stage.tri = select_tri; fs->stage.flush = select_flush; fs->stage.reset_stipple_counter = select_reset_stipple_counter; fs->stage.destroy = select_destroy; fs->ctx = ctx; return &fs->stage; }
/** * Create rasterpos "drawing" stage. */ static struct rastpos_stage * new_draw_rastpos_stage(struct gl_context *ctx, struct draw_context *draw) { struct rastpos_stage *rs = ST_CALLOC_STRUCT(rastpos_stage); GLuint i; rs->stage.draw = draw; rs->stage.next = NULL; rs->stage.point = rastpos_point; rs->stage.line = rastpos_line; rs->stage.tri = rastpos_tri; rs->stage.flush = rastpos_flush; rs->stage.destroy = rastpos_destroy; rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter; rs->stage.destroy = rastpos_destroy; rs->ctx = ctx; for (i = 0; i < ARRAY_SIZE(rs->array); i++) { rs->array[i].Size = 4; rs->array[i].Type = GL_FLOAT; rs->array[i].Format = GL_RGBA; rs->array[i].Stride = 0; rs->array[i].StrideB = 0; rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i]; rs->array[i].Enabled = GL_TRUE; rs->array[i].Normalized = GL_TRUE; rs->array[i].BufferObj = NULL; rs->arrays[i] = &rs->array[i]; } rs->prim.mode = GL_POINTS; rs->prim.indexed = 0; rs->prim.begin = 1; rs->prim.end = 1; rs->prim.weak = 0; rs->prim.start = 0; rs->prim.count = 1; return rs; }
static struct st_context * st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) { uint i; struct st_context *st = ST_CALLOC_STRUCT( st_context ); ctx->st = st; st->ctx = ctx; st->pipe = pipe; /* XXX: this is one-off, per-screen init: */ st_debug_init(); /* state tracker needs the VBO module */ _vbo_CreateContext(ctx); st->dirty.mesa = ~0; st->dirty.st = ~0; st->cso_context = cso_create_context(pipe); st_init_atoms( st ); st_init_bitmap(st); st_init_clear(st); st_init_draw( st ); st_init_generate_mipmap(st); st_init_blit(st); if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) st->internal_target = PIPE_TEXTURE_2D; else st->internal_target = PIPE_TEXTURE_RECT; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) st->state.sampler_list[i] = &st->state.samplers[i]; for (i = 0; i < 3; i++) { memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element)); st->velems_util_draw[i].src_offset = i * 4 * sizeof(float); st->velems_util_draw[i].instance_divisor = 0; st->velems_util_draw[i].vertex_buffer_index = 0; st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } /* we want all vertex data to be placed in buffer objects */ vbo_use_buffer_objects(ctx); /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; st->pixel_xfer.cache = _mesa_new_program_cache(); st->force_msaa = st_get_msaa(); /* GL limits and extensions */ st_init_limits(st); st_init_extensions(st); return st; }
/** * Allocate a renderbuffer for a an on-screen window (not a user-created * renderbuffer). The window system code determines the format. */ struct gl_renderbuffer * st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) { struct st_renderbuffer *strb; strb = ST_CALLOC_STRUCT(st_renderbuffer); if (!strb) { _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); return NULL; } _mesa_init_renderbuffer(&strb->Base, 0); strb->Base.ClassID = 0x4242; /* just a unique value */ strb->Base.NumSamples = samples; strb->Base.Format = st_pipe_format_to_mesa_format(format); strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); strb->software = sw; switch (format) { case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_A8R8G8B8_UNORM: strb->Base.InternalFormat = GL_RGBA8; break; case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: case PIPE_FORMAT_X8R8G8B8_UNORM: strb->Base.InternalFormat = GL_RGB8; break; case PIPE_FORMAT_R8G8B8A8_SRGB: case PIPE_FORMAT_B8G8R8A8_SRGB: case PIPE_FORMAT_A8R8G8B8_SRGB: strb->Base.InternalFormat = GL_SRGB8_ALPHA8; break; case PIPE_FORMAT_R8G8B8X8_SRGB: case PIPE_FORMAT_B8G8R8X8_SRGB: case PIPE_FORMAT_X8R8G8B8_SRGB: strb->Base.InternalFormat = GL_SRGB8; break; case PIPE_FORMAT_B5G5R5A1_UNORM: strb->Base.InternalFormat = GL_RGB5_A1; break; case PIPE_FORMAT_B4G4R4A4_UNORM: strb->Base.InternalFormat = GL_RGBA4; break; case PIPE_FORMAT_B5G6R5_UNORM: strb->Base.InternalFormat = GL_RGB565; break; case PIPE_FORMAT_Z16_UNORM: strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; break; case PIPE_FORMAT_Z32_UNORM: strb->Base.InternalFormat = GL_DEPTH_COMPONENT32; break; case PIPE_FORMAT_Z24_UNORM_S8_UINT: case PIPE_FORMAT_S8_UINT_Z24_UNORM: strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; break; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_X8Z24_UNORM: strb->Base.InternalFormat = GL_DEPTH_COMPONENT24; break; case PIPE_FORMAT_S8_UINT: strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; break; case PIPE_FORMAT_R16G16B16A16_SNORM: /* accum buffer */ strb->Base.InternalFormat = GL_RGBA16_SNORM; break; case PIPE_FORMAT_R16G16B16A16_UNORM: strb->Base.InternalFormat = GL_RGBA16; break; case PIPE_FORMAT_R8_UNORM: strb->Base.InternalFormat = GL_R8; break; case PIPE_FORMAT_R8G8_UNORM: strb->Base.InternalFormat = GL_RG8; break; case PIPE_FORMAT_R16_UNORM: strb->Base.InternalFormat = GL_R16; break; case PIPE_FORMAT_R16G16_UNORM: strb->Base.InternalFormat = GL_RG16; break; case PIPE_FORMAT_R32G32B32A32_FLOAT: strb->Base.InternalFormat = GL_RGBA32F; break; case PIPE_FORMAT_R16G16B16A16_FLOAT: strb->Base.InternalFormat = GL_RGBA16F; break; default: _mesa_problem(NULL, "Unexpected format %s in st_new_renderbuffer_fb", util_format_name(format)); free(strb); return NULL; } /* st-specific methods */ strb->Base.Delete = st_renderbuffer_delete; strb->Base.AllocStorage = st_renderbuffer_alloc_storage; /* surface is allocated in st_renderbuffer_alloc_storage() */ strb->surface = NULL; return &strb->Base; }
/** * 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 translated_vertex_program * find_translated_vp(struct st_context *st, struct st_vertex_program *stvp, struct st_fragment_program *stfp) { static const GLuint UNUSED = ~0; struct translated_vertex_program *xvp; const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; /* * Translate fragment program if needed. */ if (!stfp->state.tokens) { GLuint inAttr, numIn = 0; for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) { if (fragInputsRead & (1 << inAttr)) { stfp->input_to_slot[inAttr] = numIn; numIn++; } else { stfp->input_to_slot[inAttr] = UNUSED; } } stfp->num_input_slots = numIn; assert(stfp->Base.Base.NumInstructions > 1); st_translate_fragment_program(st, stfp, stfp->input_to_slot); } /* See if we've got a translated vertex program whose outputs match * the fragment program's inputs. * XXX This could be a hash lookup, using InputsRead as the key. */ for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { break; } } /* No? Allocate translated vp object now */ if (!xvp) { xvp = ST_CALLOC_STRUCT(translated_vertex_program); xvp->frag_inputs = fragInputsRead; xvp->master = stvp; xvp->next = stfp->vertex_programs; stfp->vertex_programs = xvp; } /* See if we need to translate vertex program to TGSI form */ if (xvp->serialNo != stvp->serialNo) { GLuint outAttr; const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; GLuint numVpOuts = 0; GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; GLbitfield usedGenerics = 0x0; GLbitfield usedOutputSlots = 0x0; /* Compute mapping of vertex program outputs to slots, which depends * on the fragment program's input->slot mapping. */ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { /* set defaults: */ xvp->output_to_slot[outAttr] = UNUSED; xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; xvp->output_to_semantic_index[outAttr] = 99; if (outAttr == VERT_RESULT_HPOS) { /* always put xformed position into slot zero */ GLuint slot = 0; xvp->output_to_slot[VERT_RESULT_HPOS] = slot; xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; xvp->output_to_semantic_index[outAttr] = 0; numVpOuts++; usedOutputSlots |= (1 << slot); } else if (outputsWritten & (1 << outAttr)) { /* see if the frag prog wants this vert output */ GLint fpInAttrib = vp_out_to_fp_in(outAttr); if (fpInAttrib >= 0) { GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; if (fpInSlot != ~0) { /* match this vp output to the fp input */ GLuint vpOutSlot = stfp->input_map[fpInSlot]; xvp->output_to_slot[outAttr] = vpOutSlot; xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; numVpOuts++; usedOutputSlots |= (1 << vpOutSlot); } else { #if 0 /*debug*/ printf("VP output %d not used by FP\n", outAttr); #endif } } else if (outAttr == VERT_RESULT_PSIZ) emitPntSize = GL_TRUE; else if (outAttr == VERT_RESULT_BFC0) emitBFC0 = GL_TRUE; else if (outAttr == VERT_RESULT_BFC1) emitBFC1 = GL_TRUE; } #if 0 /*debug*/ printf("assign vp output_to_slot[%d] = %d\n", outAttr, xvp->output_to_slot[outAttr]); #endif } /* must do these last */ if (emitPntSize) { GLuint slot = numVpOuts++; xvp->output_to_slot[VERT_RESULT_PSIZ] = slot; xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; usedOutputSlots |= (1 << slot); } if (emitBFC0) { GLuint slot = numVpOuts++; xvp->output_to_slot[VERT_RESULT_BFC0] = slot; xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; usedOutputSlots |= (1 << slot); } if (emitBFC1) { GLuint slot = numVpOuts++; xvp->output_to_slot[VERT_RESULT_BFC1] = slot; xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR; xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1; usedOutputSlots |= (1 << slot); } /* build usedGenerics mask */ usedGenerics = 0x0; for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]); } } /* For each vertex program output that doesn't match up to a fragment * program input, map the vertex program output to a free slot and * free generic attribute. */ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { if (outputsWritten & (1 << outAttr)) { if (xvp->output_to_slot[outAttr] == UNUSED) { GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; usedGenerics |= (1 << freeGeneric); usedOutputSlots |= (1 << freeSlot); xvp->output_to_slot[outAttr] = freeSlot; xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; xvp->output_to_semantic_index[outAttr] = freeGeneric; } } #if 0 /*debug*/ printf("vp output_to_slot[%d] = %d\n", outAttr, xvp->output_to_slot[outAttr]); #endif } assert(stvp->Base.Base.NumInstructions > 1); st_translate_vertex_program(st, stvp, xvp->output_to_slot, xvp->output_to_semantic_name, xvp->output_to_semantic_index); xvp->vp = stvp; /* translated VP is up to date now */ xvp->serialNo = stvp->serialNo; } return xvp; }
static struct st_context * st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, const struct st_config_options *options) { struct pipe_screen *screen = pipe->screen; uint i; struct st_context *st = ST_CALLOC_STRUCT( st_context ); st->options = *options; ctx->st = st; st->ctx = ctx; st->pipe = pipe; /* XXX: this is one-off, per-screen init: */ st_debug_init(); /* state tracker needs the VBO module */ _vbo_CreateContext(ctx); st->dirty.mesa = ~0; st->dirty.st = ~0; /* Create upload manager for vertex data for glBitmap, glDrawPixels, * glClear, etc. */ st->uploader = u_upload_create(st->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER); if (!screen->get_param(screen, PIPE_CAP_USER_INDEX_BUFFERS)) { st->indexbuf_uploader = u_upload_create(st->pipe, 128 * 1024, 4, PIPE_BIND_INDEX_BUFFER); } if (!screen->get_param(screen, PIPE_CAP_USER_CONSTANT_BUFFERS)) { unsigned alignment = screen->get_param(screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT); st->constbuf_uploader = u_upload_create(pipe, 128 * 1024, alignment, PIPE_BIND_CONSTANT_BUFFER); } st->cso_context = cso_create_context(pipe); st_init_atoms( st ); st_init_bitmap(st); st_init_clear(st); st_init_draw( st ); st_init_generate_mipmap(st); /* Choose texture target for glDrawPixels, glBitmap, renderbuffers */ if (pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) st->internal_target = PIPE_TEXTURE_2D; else st->internal_target = PIPE_TEXTURE_RECT; /* Vertex element objects used for drawing rectangles for glBitmap, * glDrawPixels, glClear, etc. */ for (i = 0; i < Elements(st->velems_util_draw); i++) { memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element)); st->velems_util_draw[i].src_offset = i * 4 * sizeof(float); st->velems_util_draw[i].instance_divisor = 0; st->velems_util_draw[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(st->cso_context); st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } /* we want all vertex data to be placed in buffer objects */ vbo_use_buffer_objects(ctx); /* make sure that no VBOs are left mapped when we're drawing. */ vbo_always_unmap_buffers(ctx); /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; st->pixel_xfer.cache = _mesa_new_program_cache(); st->has_stencil_export = screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT); st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3); st->prefer_blit_based_texture_transfer = screen->get_param(screen, PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER); st->needs_texcoord_semantic = screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD); st->apply_texture_swizzle_to_border_color = !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); /* GL limits and extensions */ st_init_limits(st); st_init_extensions(st); _mesa_compute_version(ctx); _mesa_initialize_dispatch_tables(ctx); _mesa_initialize_vbo_vtxfmt(ctx); return st; }
/** * One-time init for drawing bitmaps. */ static void init_bitmap_state(struct st_context *st) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; /* This function should only be called once */ assert(st->bitmap.cache == NULL); assert(st->internal_target == PIPE_TEXTURE_2D || st->internal_target == PIPE_TEXTURE_RECT); /* alloc bitmap cache object */ st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache); /* init sampler state once */ memset(&st->bitmap.sampler, 0, sizeof(st->bitmap.sampler)); st->bitmap.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; st->bitmap.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; st->bitmap.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; st->bitmap.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; st->bitmap.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; st->bitmap.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; st->bitmap.sampler.normalized_coords = st->internal_target == PIPE_TEXTURE_2D; st->bitmap.atlas_sampler = st->bitmap.sampler; st->bitmap.atlas_sampler.normalized_coords = 0; /* init baseline rasterizer state once */ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); st->bitmap.rasterizer.half_pixel_center = 1; st->bitmap.rasterizer.bottom_edge_rule = 1; st->bitmap.rasterizer.depth_clip = 1; /* find a usable texture format */ if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, st->internal_target, 0, PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; } else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, st->internal_target, 0, PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; } else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, st->internal_target, 0, PIPE_BIND_SAMPLER_VIEW)) { st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; } else { /* XXX support more formats */ assert(0); } /* Create the vertex shader */ { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_COLOR, st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0, 0 }; st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, semantic_names, semantic_indexes, FALSE); } reset_cache(st); }
static struct st_context * st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, const struct st_config_options *options) { struct pipe_screen *screen = pipe->screen; uint i; struct st_context *st = ST_CALLOC_STRUCT( st_context ); st->options = *options; ctx->st = st; st->ctx = ctx; st->pipe = pipe; /* XXX: this is one-off, per-screen init: */ st_debug_init(); /* state tracker needs the VBO module */ _vbo_CreateContext(ctx); st->dirty.mesa = ~0; st->dirty.st = ~0; /* Create upload manager for vertex data for glBitmap, glDrawPixels, * glClear, etc. */ st->uploader = u_upload_create(st->pipe, 65536, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM); if (!screen->get_param(screen, PIPE_CAP_USER_INDEX_BUFFERS)) { st->indexbuf_uploader = u_upload_create(st->pipe, 128 * 1024, PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM); } if (!screen->get_param(screen, PIPE_CAP_USER_CONSTANT_BUFFERS)) st->constbuf_uploader = u_upload_create(pipe, 128 * 1024, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM); st->cso_context = cso_create_context(pipe); st_init_atoms( st ); st_init_bitmap(st); st_init_clear(st); st_init_draw( st ); /* Choose texture target for glDrawPixels, glBitmap, renderbuffers */ if (pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) st->internal_target = PIPE_TEXTURE_2D; else st->internal_target = PIPE_TEXTURE_RECT; /* Vertex element objects used for drawing rectangles for glBitmap, * glDrawPixels, glClear, etc. */ for (i = 0; i < ARRAY_SIZE(st->velems_util_draw); i++) { memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element)); st->velems_util_draw[i].src_offset = i * 4 * sizeof(float); st->velems_util_draw[i].instance_divisor = 0; st->velems_util_draw[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(st->cso_context); st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } /* we want all vertex data to be placed in buffer objects */ vbo_use_buffer_objects(ctx); /* make sure that no VBOs are left mapped when we're drawing. */ vbo_always_unmap_buffers(ctx); /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; st->has_stencil_export = screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT); st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3); st->has_etc1 = screen->is_format_supported(screen, PIPE_FORMAT_ETC1_RGB8, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW); st->has_etc2 = screen->is_format_supported(screen, PIPE_FORMAT_ETC2_RGB8, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW); st->prefer_blit_based_texture_transfer = screen->get_param(screen, PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER); st->force_persample_in_shader = screen->get_param(screen, PIPE_CAP_SAMPLE_SHADING) && !screen->get_param(screen, PIPE_CAP_FORCE_PERSAMPLE_INTERP); st->has_shareable_shaders = screen->get_param(screen, PIPE_CAP_SHAREABLE_SHADERS); st->needs_texcoord_semantic = screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD); st->apply_texture_swizzle_to_border_color = !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); st->has_time_elapsed = screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED); st->has_half_float_packing = screen->get_param(screen, PIPE_CAP_TGSI_PACK_HALF_FLOAT); st->has_multi_draw_indirect = screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT); /* GL limits and extensions */ st_init_limits(st->pipe->screen, &ctx->Const, &ctx->Extensions); st_init_extensions(st->pipe->screen, &ctx->Const, &ctx->Extensions, &st->options, ctx->Mesa_DXTn); if (st_have_perfmon(st)) { ctx->Extensions.AMD_performance_monitor = GL_TRUE; } /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) { st->clamp_vert_color_in_shader = GL_TRUE; } if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) { st->clamp_frag_color_in_shader = GL_TRUE; } /* For drivers which cannot do color clamping, it's better to just * disable ARB_color_buffer_float in the core profile, because * the clamping is deprecated there anyway. */ if (ctx->API == API_OPENGL_CORE && (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) { st->clamp_vert_color_in_shader = GL_FALSE; st->clamp_frag_color_in_shader = GL_FALSE; ctx->Extensions.ARB_color_buffer_float = GL_FALSE; } } /* called after _mesa_create_context/_mesa_init_point, fix default user * settable max point size up */ st->ctx->Point.MaxSize = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA); /* For vertex shaders, make sure not to emit saturate when SM 3.0 is not supported */ ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].EmitNoSat = !st->has_shader_model3; if (!ctx->Extensions.ARB_gpu_shader5) { for (i = 0; i < MESA_SHADER_STAGES; i++) ctx->Const.ShaderCompilerOptions[i].EmitNoIndirectSampler = true; } /* Set which shader types can be compiled at link time. */ st->shader_has_one_variant[MESA_SHADER_VERTEX] = st->has_shareable_shaders && !st->clamp_vert_color_in_shader; st->shader_has_one_variant[MESA_SHADER_FRAGMENT] = st->has_shareable_shaders && !st->clamp_frag_color_in_shader && !st->force_persample_in_shader; st->shader_has_one_variant[MESA_SHADER_TESS_CTRL] = st->has_shareable_shaders; st->shader_has_one_variant[MESA_SHADER_TESS_EVAL] = st->has_shareable_shaders; st->shader_has_one_variant[MESA_SHADER_GEOMETRY] = st->has_shareable_shaders; _mesa_compute_version(ctx); if (ctx->Version == 0) { /* This can happen when a core profile was requested, but the driver * does not support some features of GL 3.1 or later. */ st_destroy_context_priv(st); return NULL; } _mesa_initialize_dispatch_tables(ctx); _mesa_initialize_vbo_vtxfmt(ctx); return st; }