static void convert_sampler(struct st_context *st, struct pipe_sampler_state *sampler, GLuint texUnit) { const struct gl_texture_object *texobj; struct gl_context *ctx = st->ctx; const struct gl_sampler_object *msamp; GLenum texBaseFormat; texobj = ctx->Texture.Unit[texUnit]._Current; if (!texobj) { texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); msamp = &texobj->Sampler; } else { msamp = _mesa_get_samplerobj(ctx, texUnit); } texBaseFormat = _mesa_texture_base_format(texobj); memset(sampler, 0, sizeof(*sampler)); sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) sampler->normalized_coords = 1; sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; sampler->min_lod = MAX2(msamp->MinLod, 0.0f); sampler->max_lod = msamp->MaxLod; if (sampler->max_lod < sampler->min_lod) { /* The GL spec doesn't seem to specify what to do in this case. * Swap the values. */ float tmp = sampler->max_lod; sampler->max_lod = sampler->min_lod; sampler->min_lod = tmp; assert(sampler->min_lod <= sampler->max_lod); } /* For non-black borders... */ if (msamp->BorderColor.ui[0] || msamp->BorderColor.ui[1] || msamp->BorderColor.ui[2] || msamp->BorderColor.ui[3]) { const struct st_texture_object *stobj = st_texture_object_const(texobj); const GLboolean is_integer = texobj->_IsIntegerFormat; const struct pipe_sampler_view *sv = NULL; union pipe_color_union border_color; GLuint i; /* Just search for the first used view. We can do this because the swizzle is per-texture, not per context. */ /* XXX: clean that up to not use the sampler view at all */ for (i = 0; i < stobj->num_sampler_views; ++i) { if (stobj->sampler_views[i]) { sv = stobj->sampler_views[i]; break; } } if (st->apply_texture_swizzle_to_border_color && sv) { const unsigned char swz[4] = { sv->swizzle_r, sv->swizzle_g, sv->swizzle_b, sv->swizzle_a, }; st_translate_color(&msamp->BorderColor, &border_color, texBaseFormat, is_integer); util_format_apply_color_swizzle(&sampler->border_color, &border_color, swz, is_integer); } else { st_translate_color(&msamp->BorderColor, &sampler->border_color, texBaseFormat, is_integer); } } sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? 0 : (GLuint) msamp->MaxAnisotropy); /* If sampling a depth texture and using shadow comparison */ if ((texBaseFormat == GL_DEPTH_COMPONENT || texBaseFormat == GL_DEPTH_STENCIL) && msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc); } sampler->seamless_cube_map = ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; }
/** * Do glClear by drawing a quadrilateral. * The vertices of the quad will be computed from the * ctx->DrawBuffer->_X/Ymin/max fields. */ static void clear_with_quad(struct gl_context *ctx, GLboolean color, GLboolean depth, GLboolean stencil) { struct st_context *st = st_context(ctx); const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f; 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; union pipe_color_union clearColor; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", x0, y0, x1, y1); */ cso_save_blend(st->cso_context); cso_save_stencil_ref(st->cso_context); cso_save_depth_stencil_alpha(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_viewport(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); cso_save_vertex_buffers(st->cso_context); /* blend state: RGBA masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; if (color) { if (ctx->Color.ColorMask[0][0]) blend.rt[0].colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[0][1]) blend.rt[0].colormask |= PIPE_MASK_G; if (ctx->Color.ColorMask[0][2]) blend.rt[0].colormask |= PIPE_MASK_B; if (ctx->Color.ColorMask[0][3]) blend.rt[0].colormask |= PIPE_MASK_A; if (st->ctx->Color.DitherFlag) blend.dither = 1; } cso_set_blend(st->cso_context, &blend); } /* depth_stencil state: always pass/set to ref value */ { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); if (depth) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } if (stencil) { struct pipe_stencil_ref stencil_ref; memset(&stencil_ref, 0, sizeof(stencil_ref)); depth_stencil.stencil[0].enabled = 1; depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].valuemask = 0xff; depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; stencil_ref.ref_value[0] = ctx->Stencil.Clear; cso_set_stencil_ref(st->cso_context, &stencil_ref); } cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); cso_set_stream_outputs(st->cso_context, 0, NULL, 0); cso_set_rasterizer(st->cso_context, &st->clear.raster); /* viewport state: viewport matching window dims */ { const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); struct pipe_viewport_state vp; vp.scale[0] = 0.5f * fb_width; vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f); vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * fb_width; vp.translate[1] = 0.5f * fb_height; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(st->cso_context, &vp); } set_fragment_shader(st); set_vertex_shader(st); cso_set_geometry_shader_handle(st->cso_context, NULL); if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { st_translate_color(ctx->Color.ClearColor.f, ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, clearColor.f); } /* 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); cso_restore_stencil_ref(st->cso_context); cso_restore_depth_stencil_alpha(st->cso_context); cso_restore_rasterizer(st->cso_context); cso_restore_viewport(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_vertex_buffers(st->cso_context); cso_restore_stream_outputs(st->cso_context); }
/** * Called via ctx->Driver.Clear() */ static void st_Clear(struct gl_context *ctx, GLbitfield mask) { static const GLbitfield BUFFER_BITS_DS = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); struct st_context *st = st_context(ctx); struct gl_renderbuffer *depthRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *stencilRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; GLbitfield quad_buffers = 0x0; GLbitfield clear_buffers = 0x0; GLuint i; /* This makes sure the pipe has the latest scissor, etc values */ st_validate_state( st ); if (mask & BUFFER_BITS_COLOR) { for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); if (!strb || !strb->surface) continue; if (check_clear_color_with_quad( ctx, rb )) quad_buffers |= PIPE_CLEAR_COLOR; else clear_buffers |= PIPE_CLEAR_COLOR; } } } if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { /* clearing combined depth + stencil */ struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { if (check_clear_depth_stencil_with_quad(ctx, depthRb)) quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; else clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; } } else { /* separate depth/stencil clears */ /* I don't think truly separate buffers are actually possible in gallium or hw? */ if (mask & BUFFER_BIT_DEPTH) { struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { if (check_clear_depth_with_quad(ctx, depthRb, st->clear.enable_ds_separate)) quad_buffers |= PIPE_CLEAR_DEPTH; else clear_buffers |= PIPE_CLEAR_DEPTH; } } if (mask & BUFFER_BIT_STENCIL) { struct st_renderbuffer *strb = st_renderbuffer(stencilRb); if (strb->surface) { if (check_clear_stencil_with_quad(ctx, stencilRb, st->clear.enable_ds_separate)) quad_buffers |= PIPE_CLEAR_STENCIL; else clear_buffers |= PIPE_CLEAR_STENCIL; } } } /* * If we're going to use clear_with_quad() for any reason, use it for * everything possible. */ if (quad_buffers) { quad_buffers |= clear_buffers; clear_with_quad(ctx, quad_buffers & PIPE_CLEAR_COLOR, quad_buffers & PIPE_CLEAR_DEPTH, quad_buffers & PIPE_CLEAR_STENCIL); } else if (clear_buffers) { /* driver cannot know it can clear everything if the buffer * is a combined depth/stencil buffer but this wasn't actually * required from the visual. Hence fix this up to avoid potential * read-modify-write in the driver. */ union pipe_color_union clearColor; 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.f, ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, clearColor.f); } st->pipe->clear(st->pipe, clear_buffers, &clearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } if (mask & BUFFER_BIT_ACCUM) _mesa_clear_accum_buffer(ctx); }
static void convert_sampler(struct st_context *st, struct pipe_sampler_state *sampler, GLuint texUnit) { struct gl_texture_object *texobj; struct gl_context *ctx = st->ctx; struct gl_sampler_object *msamp; texobj = ctx->Texture.Unit[texUnit]._Current; if (!texobj) { texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); } msamp = _mesa_get_samplerobj(ctx, texUnit); memset(sampler, 0, sizeof(*sampler)); sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) sampler->normalized_coords = 1; sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; sampler->min_lod = CLAMP(msamp->MinLod, 0.0f, (GLfloat) texobj->MaxLevel - texobj->BaseLevel); sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, msamp->MaxLod); if (sampler->max_lod < sampler->min_lod) { /* The GL spec doesn't seem to specify what to do in this case. * Swap the values. */ float tmp = sampler->max_lod; sampler->max_lod = sampler->min_lod; sampler->min_lod = tmp; assert(sampler->min_lod <= sampler->max_lod); } if (msamp->BorderColor.ui[0] || msamp->BorderColor.ui[1] || msamp->BorderColor.ui[2] || msamp->BorderColor.ui[3]) { struct st_texture_object *stobj = st_texture_object(texobj); struct gl_texture_image *teximg; GLboolean is_integer = GL_FALSE; union pipe_color_union border_color; teximg = texobj->Image[0][texobj->BaseLevel]; if (teximg) { is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat); } if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) { const unsigned char swz[4] = { stobj->sampler_view->swizzle_r, stobj->sampler_view->swizzle_g, stobj->sampler_view->swizzle_b, stobj->sampler_view->swizzle_a, }; st_translate_color(&msamp->BorderColor, &border_color, teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); util_format_apply_color_swizzle(&sampler->border_color, &border_color, swz, is_integer); } else { st_translate_color(&msamp->BorderColor, &sampler->border_color, teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); } } sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? 0 : (GLuint) msamp->MaxAnisotropy); /* only care about ARB_shadow, not SGI shadow */ if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc); } sampler->seamless_cube_map = ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; }