14a49301eSmrg/* 24a49301eSmrg * Mesa 3-D graphics library 34a49301eSmrg * 44a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the "Software"), 84a49301eSmrg * to deal in the Software without restriction, including without limitation 94a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 104a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the 114a49301eSmrg * Software is furnished to do so, subject to the following conditions: 124a49301eSmrg * 134a49301eSmrg * The above copyright notice and this permission notice shall be included 144a49301eSmrg * in all copies or substantial portions of the Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 174a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 234a49301eSmrg */ 244a49301eSmrg 254a49301eSmrg/** 264a49301eSmrg * Meta operations. Some GL operations can be expressed in terms of 274a49301eSmrg * other GL operations. For example, glBlitFramebuffer() can be done 284a49301eSmrg * with texture mapping and glClear() can be done with polygon rendering. 294a49301eSmrg * 304a49301eSmrg * \author Brian Paul 314a49301eSmrg */ 324a49301eSmrg 334a49301eSmrg 344a49301eSmrg#include "main/glheader.h" 354a49301eSmrg#include "main/mtypes.h" 363464ebd5Sriastradh#include "main/arbprogram.h" 374a49301eSmrg#include "main/arrayobj.h" 384a49301eSmrg#include "main/blend.h" 39af69d88dSmrg#include "main/blit.h" 404a49301eSmrg#include "main/bufferobj.h" 414a49301eSmrg#include "main/buffers.h" 42af69d88dSmrg#include "main/clear.h" 433464ebd5Sriastradh#include "main/condrender.h" 4401e04c3fSmrg#include "main/draw.h" 457ec681f3Smrg#include "main/draw_validate.h" 464a49301eSmrg#include "main/depth.h" 474a49301eSmrg#include "main/enable.h" 484a49301eSmrg#include "main/fbobject.h" 49af69d88dSmrg#include "main/feedback.h" 504a49301eSmrg#include "main/formats.h" 51af69d88dSmrg#include "main/format_unpack.h" 5201e04c3fSmrg#include "main/framebuffer.h" 53af69d88dSmrg#include "main/glformats.h" 544a49301eSmrg#include "main/image.h" 554a49301eSmrg#include "main/macros.h" 564a49301eSmrg#include "main/matrix.h" 574a49301eSmrg#include "main/mipmap.h" 58af69d88dSmrg#include "main/multisample.h" 59af69d88dSmrg#include "main/objectlabel.h" 60af69d88dSmrg#include "main/pipelineobj.h" 61af69d88dSmrg#include "main/pixel.h" 623464ebd5Sriastradh#include "main/pbo.h" 634a49301eSmrg#include "main/polygon.h" 64af69d88dSmrg#include "main/queryobj.h" 654a49301eSmrg#include "main/readpix.h" 6601e04c3fSmrg#include "main/renderbuffer.h" 674a49301eSmrg#include "main/scissor.h" 683464ebd5Sriastradh#include "main/shaderapi.h" 693464ebd5Sriastradh#include "main/shaderobj.h" 704a49301eSmrg#include "main/state.h" 714a49301eSmrg#include "main/stencil.h" 724a49301eSmrg#include "main/texobj.h" 734a49301eSmrg#include "main/texenv.h" 74af69d88dSmrg#include "main/texgetimage.h" 754a49301eSmrg#include "main/teximage.h" 764a49301eSmrg#include "main/texparam.h" 774a49301eSmrg#include "main/texstate.h" 78af69d88dSmrg#include "main/texstore.h" 79af69d88dSmrg#include "main/transformfeedback.h" 80af69d88dSmrg#include "main/uniforms.h" 814a49301eSmrg#include "main/varray.h" 824a49301eSmrg#include "main/viewport.h" 83af69d88dSmrg#include "main/samplerobj.h" 843464ebd5Sriastradh#include "program/program.h" 854a49301eSmrg#include "swrast/swrast.h" 864a49301eSmrg#include "drivers/common/meta.h" 87af69d88dSmrg#include "main/enums.h" 88af69d88dSmrg#include "main/glformats.h" 8901e04c3fSmrg#include "util/bitscan.h" 90af69d88dSmrg#include "util/ralloc.h" 9101e04c3fSmrg#include "compiler/nir/nir.h" 9201e04c3fSmrg#include "util/u_math.h" 937ec681f3Smrg#include "util/u_memory.h" 944a49301eSmrg 954a49301eSmrg/** Return offset in bytes of the field within a vertex struct */ 964a49301eSmrg#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) 974a49301eSmrg 98af69d88dSmrgstatic void 99af69d88dSmrgmeta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl); 1004a49301eSmrg 101af69d88dSmrgstatic struct blit_shader * 102af69d88dSmrgchoose_blit_shader(GLenum target, struct blit_shader_table *table); 1034a49301eSmrg 10401e04c3fSmrgstatic void cleanup_temp_texture(struct gl_context *ctx, 10501e04c3fSmrg struct temp_texture *tex); 10601e04c3fSmrgstatic void meta_glsl_clear_cleanup(struct gl_context *ctx, 10701e04c3fSmrg struct clear_state *clear); 108a8bb7a65Smayastatic void meta_copypix_cleanup(struct gl_context *ctx, 109a8bb7a65Smaya struct copypix_state *copypix); 11001e04c3fSmrgstatic void meta_decompress_cleanup(struct gl_context *ctx, 11101e04c3fSmrg struct decompress_state *decompress); 11201e04c3fSmrgstatic void meta_drawpix_cleanup(struct gl_context *ctx, 11301e04c3fSmrg struct drawpix_state *drawpix); 1147ec681f3Smrgstatic void meta_drawtex_cleanup(struct gl_context *ctx, 1157ec681f3Smrg struct drawtex_state *drawtex); 1167ec681f3Smrgstatic void meta_bitmap_cleanup(struct gl_context *ctx, 1177ec681f3Smrg struct bitmap_state *bitmap); 1184a49301eSmrg 119af69d88dSmrgvoid 12001e04c3fSmrg_mesa_meta_framebuffer_texture_image(struct gl_context *ctx, 12101e04c3fSmrg struct gl_framebuffer *fb, 12201e04c3fSmrg GLenum attachment, 12301e04c3fSmrg struct gl_texture_image *texImage, 12401e04c3fSmrg GLuint layer) 1254a49301eSmrg{ 126af69d88dSmrg struct gl_texture_object *texObj = texImage->TexObject; 127af69d88dSmrg int level = texImage->Level; 12801e04c3fSmrg const GLenum texTarget = texObj->Target == GL_TEXTURE_CUBE_MAP 12901e04c3fSmrg ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face 13001e04c3fSmrg : texObj->Target; 131af69d88dSmrg 13201e04c3fSmrg struct gl_renderbuffer_attachment *att = 13301e04c3fSmrg _mesa_get_and_validate_attachment(ctx, fb, attachment, __func__); 13401e04c3fSmrg assert(att); 1354a49301eSmrg 13601e04c3fSmrg _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, texTarget, 137a8bb7a65Smaya level, att->NumSamples, layer, false); 138af69d88dSmrg} 1394a49301eSmrg 14001e04c3fSmrgstatic struct gl_shader * 14101e04c3fSmrgmeta_compile_shader_with_debug(struct gl_context *ctx, gl_shader_stage stage, 14201e04c3fSmrg const GLcharARB *source) 1434a49301eSmrg{ 14401e04c3fSmrg const GLuint name = ~0; 14501e04c3fSmrg struct gl_shader *sh; 14601e04c3fSmrg 14701e04c3fSmrg sh = _mesa_new_shader(name, stage); 14801e04c3fSmrg sh->Source = strdup(source); 14901e04c3fSmrg sh->CompileStatus = COMPILE_FAILURE; 15001e04c3fSmrg _mesa_compile_shader(ctx, sh); 15101e04c3fSmrg 15201e04c3fSmrg if (!sh->CompileStatus) { 15301e04c3fSmrg if (sh->InfoLog) { 15401e04c3fSmrg _mesa_problem(ctx, 15501e04c3fSmrg "meta program compile failed:\n%s\nsource:\n%s\n", 15601e04c3fSmrg sh->InfoLog, source); 15701e04c3fSmrg } 1584a49301eSmrg 15901e04c3fSmrg _mesa_reference_shader(ctx, &sh, NULL); 160af69d88dSmrg } 1614a49301eSmrg 16201e04c3fSmrg return sh; 163af69d88dSmrg} 1644a49301eSmrg 16501e04c3fSmrgvoid 16601e04c3fSmrg_mesa_meta_link_program_with_debug(struct gl_context *ctx, 16701e04c3fSmrg struct gl_shader_program *sh_prog) 1684a49301eSmrg{ 16901e04c3fSmrg _mesa_link_program(ctx, sh_prog); 1704a49301eSmrg 17101e04c3fSmrg if (!sh_prog->data->LinkStatus) { 17201e04c3fSmrg _mesa_problem(ctx, "meta program link failed:\n%s", 17301e04c3fSmrg sh_prog->data->InfoLog); 17401e04c3fSmrg } 17501e04c3fSmrg} 176af69d88dSmrg 17701e04c3fSmrgvoid 17801e04c3fSmrg_mesa_meta_use_program(struct gl_context *ctx, 17901e04c3fSmrg struct gl_shader_program *sh_prog) 18001e04c3fSmrg{ 18101e04c3fSmrg /* Attach shader state to the binding point */ 18201e04c3fSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader); 1834a49301eSmrg 18401e04c3fSmrg /* Update the program */ 18501e04c3fSmrg _mesa_use_shader_program(ctx, sh_prog); 186af69d88dSmrg} 187af69d88dSmrg 188af69d88dSmrgvoid 189af69d88dSmrg_mesa_meta_compile_and_link_program(struct gl_context *ctx, 190af69d88dSmrg const char *vs_source, 191af69d88dSmrg const char *fs_source, 192af69d88dSmrg const char *name, 19301e04c3fSmrg struct gl_shader_program **out_sh_prog) 194af69d88dSmrg{ 19501e04c3fSmrg struct gl_shader_program *sh_prog; 19601e04c3fSmrg const GLuint id = ~0; 19701e04c3fSmrg 19801e04c3fSmrg sh_prog = _mesa_new_shader_program(id); 19901e04c3fSmrg sh_prog->Label = strdup(name); 20001e04c3fSmrg sh_prog->NumShaders = 2; 20101e04c3fSmrg sh_prog->Shaders = malloc(2 * sizeof(struct gl_shader *)); 20201e04c3fSmrg sh_prog->Shaders[0] = 20301e04c3fSmrg meta_compile_shader_with_debug(ctx, MESA_SHADER_VERTEX, vs_source); 20401e04c3fSmrg sh_prog->Shaders[1] = 20501e04c3fSmrg meta_compile_shader_with_debug(ctx, MESA_SHADER_FRAGMENT, fs_source); 20601e04c3fSmrg 20701e04c3fSmrg _mesa_meta_link_program_with_debug(ctx, sh_prog); 20801e04c3fSmrg 20901e04c3fSmrg struct gl_program *fp = 21001e04c3fSmrg sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; 21101e04c3fSmrg 21201e04c3fSmrg /* texelFetch() can break GL_SKIP_DECODE_EXT, but many meta passes want 21301e04c3fSmrg * to use both together; pretend that we're not using texelFetch to hack 21401e04c3fSmrg * around this bad interaction. This is a bit fragile as it may break 21501e04c3fSmrg * if you re-run the pass that gathers this info, but we probably won't... 21601e04c3fSmrg */ 2177ec681f3Smrg BITSET_ZERO(fp->info.textures_used_by_txf); 21801e04c3fSmrg if (fp->nir) 2197ec681f3Smrg BITSET_ZERO(fp->nir->info.textures_used_by_txf); 22001e04c3fSmrg 22101e04c3fSmrg _mesa_meta_use_program(ctx, sh_prog); 22201e04c3fSmrg 22301e04c3fSmrg *out_sh_prog = sh_prog; 224af69d88dSmrg} 2254a49301eSmrg 2264a49301eSmrg/** 227af69d88dSmrg * Generate a generic shader to blit from a texture to a framebuffer 228af69d88dSmrg * 229af69d88dSmrg * \param ctx Current GL context 230af69d88dSmrg * \param texTarget Texture target that will be the source of the blit 231af69d88dSmrg * 232af69d88dSmrg * \returns a handle to a shader program on success or zero on failure. 2334a49301eSmrg */ 234af69d88dSmrgvoid 235af69d88dSmrg_mesa_meta_setup_blit_shader(struct gl_context *ctx, 236af69d88dSmrg GLenum target, 23701e04c3fSmrg bool do_depth, 238af69d88dSmrg struct blit_shader_table *table) 2394a49301eSmrg{ 240af69d88dSmrg char *vs_source, *fs_source; 241af69d88dSmrg struct blit_shader *shader = choose_blit_shader(target, table); 24201e04c3fSmrg const char *fs_input, *vs_preprocess, *fs_preprocess; 24301e04c3fSmrg void *mem_ctx; 244af69d88dSmrg 245af69d88dSmrg if (ctx->Const.GLSLVersion < 130) { 246af69d88dSmrg vs_preprocess = ""; 247af69d88dSmrg fs_preprocess = "#extension GL_EXT_texture_array : enable"; 248af69d88dSmrg fs_input = "varying"; 249af69d88dSmrg } else { 250af69d88dSmrg vs_preprocess = "#version 130"; 251af69d88dSmrg fs_preprocess = "#version 130"; 252af69d88dSmrg fs_input = "in"; 253af69d88dSmrg shader->func = "texture"; 254af69d88dSmrg } 255af69d88dSmrg 256af69d88dSmrg assert(shader != NULL); 257af69d88dSmrg 25801e04c3fSmrg if (shader->shader_prog != NULL) { 25901e04c3fSmrg _mesa_meta_use_program(ctx, shader->shader_prog); 260af69d88dSmrg return; 261af69d88dSmrg } 262af69d88dSmrg 26301e04c3fSmrg mem_ctx = ralloc_context(NULL); 26401e04c3fSmrg 265af69d88dSmrg vs_source = ralloc_asprintf(mem_ctx, 266af69d88dSmrg "%s\n" 26701e04c3fSmrg "#extension GL_ARB_explicit_attrib_location: enable\n" 26801e04c3fSmrg "layout(location = 0) in vec2 position;\n" 26901e04c3fSmrg "layout(location = 1) in vec4 textureCoords;\n" 27001e04c3fSmrg "out vec4 texCoords;\n" 271af69d88dSmrg "void main()\n" 272af69d88dSmrg "{\n" 273af69d88dSmrg " texCoords = textureCoords;\n" 274af69d88dSmrg " gl_Position = vec4(position, 0.0, 1.0);\n" 275af69d88dSmrg "}\n", 27601e04c3fSmrg vs_preprocess); 277af69d88dSmrg 278af69d88dSmrg fs_source = ralloc_asprintf(mem_ctx, 279af69d88dSmrg "%s\n" 280af69d88dSmrg "#extension GL_ARB_texture_cube_map_array: enable\n" 281af69d88dSmrg "uniform %s texSampler;\n" 282af69d88dSmrg "%s vec4 texCoords;\n" 283af69d88dSmrg "void main()\n" 284af69d88dSmrg "{\n" 285af69d88dSmrg " gl_FragColor = %s(texSampler, %s);\n" 28601e04c3fSmrg "%s" 287af69d88dSmrg "}\n", 288af69d88dSmrg fs_preprocess, shader->type, fs_input, 28901e04c3fSmrg shader->func, shader->texcoords, 29001e04c3fSmrg do_depth ? " gl_FragDepth = gl_FragColor.x;\n" : ""); 291af69d88dSmrg 292af69d88dSmrg _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, 293af69d88dSmrg ralloc_asprintf(mem_ctx, "%s blit", 294af69d88dSmrg shader->type), 295af69d88dSmrg &shader->shader_prog); 296af69d88dSmrg ralloc_free(mem_ctx); 297af69d88dSmrg} 2984a49301eSmrg 2994a49301eSmrg/** 300af69d88dSmrg * Configure vertex buffer and vertex array objects for tests 301af69d88dSmrg * 30201e04c3fSmrg * Regardless of whether a new VAO is created, the object referenced by \c VAO 30301e04c3fSmrg * will be bound into the GL state vector when this function terminates. The 30401e04c3fSmrg * object referenced by \c VBO will \b not be bound. 305af69d88dSmrg * 306af69d88dSmrg * \param VAO Storage for vertex array object handle. If 0, a new VAO 307af69d88dSmrg * will be created. 30801e04c3fSmrg * \param buf_obj Storage for vertex buffer object pointer. If \c NULL, a new VBO 309af69d88dSmrg * will be created. The new VBO will have storage for 4 310af69d88dSmrg * \c vertex structures. 311af69d88dSmrg * \param use_generic_attributes Should generic attributes 0 and 1 be used, 312af69d88dSmrg * or should traditional, fixed-function color and texture 313af69d88dSmrg * coordinate be used? 314af69d88dSmrg * \param vertex_size Number of components for attribute 0 / vertex. 315af69d88dSmrg * \param texcoord_size Number of components for attribute 1 / texture 316af69d88dSmrg * coordinate. If this is 0, attribute 1 will not be set or 317af69d88dSmrg * enabled. 318af69d88dSmrg * \param color_size Number of components for attribute 1 / primary color. 319af69d88dSmrg * If this is 0, attribute 1 will not be set or enabled. 320af69d88dSmrg * 321af69d88dSmrg * \note If \c use_generic_attributes is \c true, \c color_size must be zero. 322af69d88dSmrg * Use \c texcoord_size instead. 3234a49301eSmrg */ 324af69d88dSmrgvoid 32501e04c3fSmrg_mesa_meta_setup_vertex_objects(struct gl_context *ctx, 32601e04c3fSmrg GLuint *VAO, struct gl_buffer_object **buf_obj, 327af69d88dSmrg bool use_generic_attributes, 328af69d88dSmrg unsigned vertex_size, unsigned texcoord_size, 329af69d88dSmrg unsigned color_size) 3304a49301eSmrg{ 331af69d88dSmrg if (*VAO == 0) { 33201e04c3fSmrg struct gl_vertex_array_object *array_obj; 33301e04c3fSmrg assert(*buf_obj == NULL); 3344a49301eSmrg 335af69d88dSmrg /* create vertex array object */ 336af69d88dSmrg _mesa_GenVertexArrays(1, VAO); 337af69d88dSmrg _mesa_BindVertexArray(*VAO); 338af69d88dSmrg 33901e04c3fSmrg array_obj = _mesa_lookup_vao(ctx, *VAO); 34001e04c3fSmrg assert(array_obj != NULL); 34101e04c3fSmrg 342af69d88dSmrg /* create vertex array buffer */ 34301e04c3fSmrg *buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF); 34401e04c3fSmrg if (*buf_obj == NULL) 34501e04c3fSmrg return; 34601e04c3fSmrg 34701e04c3fSmrg _mesa_buffer_data(ctx, *buf_obj, GL_NONE, 4 * sizeof(struct vertex), NULL, 34801e04c3fSmrg GL_DYNAMIC_DRAW, __func__); 349af69d88dSmrg 350af69d88dSmrg /* setup vertex arrays */ 3517ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 352af69d88dSmrg if (use_generic_attributes) { 353af69d88dSmrg assert(color_size == 0); 354af69d88dSmrg 35501e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_GENERIC(0), 35601e04c3fSmrg vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE, 35701e04c3fSmrg GL_FALSE, GL_FALSE, 35801e04c3fSmrg offsetof(struct vertex, x)); 35901e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_GENERIC(0), 3607ec681f3Smrg *buf_obj, 0, sizeof(struct vertex), false, 3617ec681f3Smrg false); 36201e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, 36301e04c3fSmrg VERT_ATTRIB_GENERIC(0)); 364af69d88dSmrg if (texcoord_size > 0) { 36501e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_GENERIC(1), 36601e04c3fSmrg texcoord_size, GL_FLOAT, GL_RGBA, 36701e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, 36801e04c3fSmrg offsetof(struct vertex, tex)); 36901e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_GENERIC(1), 3707ec681f3Smrg *buf_obj, 0, sizeof(struct vertex), false, 3717ec681f3Smrg false); 37201e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, 37301e04c3fSmrg VERT_ATTRIB_GENERIC(1)); 374af69d88dSmrg } 375af69d88dSmrg } else { 37601e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_POS, 37701e04c3fSmrg vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE, 37801e04c3fSmrg GL_FALSE, GL_FALSE, 37901e04c3fSmrg offsetof(struct vertex, x)); 38001e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_POS, 3817ec681f3Smrg *buf_obj, 0, sizeof(struct vertex), false, 3827ec681f3Smrg false); 38301e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_POS); 384af69d88dSmrg 385af69d88dSmrg if (texcoord_size > 0) { 38601e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_TEX(0), 38701e04c3fSmrg vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE, 38801e04c3fSmrg GL_FALSE, GL_FALSE, 38901e04c3fSmrg offsetof(struct vertex, tex)); 39001e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_TEX(0), 3917ec681f3Smrg *buf_obj, 0, sizeof(struct vertex), false, 3927ec681f3Smrg false); 39301e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, 39401e04c3fSmrg VERT_ATTRIB_TEX(0)); 395af69d88dSmrg } 3964a49301eSmrg 397af69d88dSmrg if (color_size > 0) { 39801e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_COLOR0, 39901e04c3fSmrg vertex_size, GL_FLOAT, GL_RGBA, GL_FALSE, 40001e04c3fSmrg GL_FALSE, GL_FALSE, 40101e04c3fSmrg offsetof(struct vertex, r)); 40201e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_COLOR0, 4037ec681f3Smrg *buf_obj, 0, sizeof(struct vertex), false, 4047ec681f3Smrg false); 40501e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, 40601e04c3fSmrg VERT_ATTRIB_COLOR0); 407af69d88dSmrg } 408af69d88dSmrg } 409af69d88dSmrg } else { 410af69d88dSmrg _mesa_BindVertexArray(*VAO); 411af69d88dSmrg } 412af69d88dSmrg} 4134a49301eSmrg 4144a49301eSmrg/** 4154a49301eSmrg * Initialize meta-ops for a context. 4164a49301eSmrg * To be called once during context creation. 4174a49301eSmrg */ 4184a49301eSmrgvoid 4193464ebd5Sriastradh_mesa_meta_init(struct gl_context *ctx) 4204a49301eSmrg{ 42101e04c3fSmrg assert(!ctx->Meta); 4224a49301eSmrg 4234a49301eSmrg ctx->Meta = CALLOC_STRUCT(gl_meta_state); 4244a49301eSmrg} 4254a49301eSmrg 4264a49301eSmrg/** 4274a49301eSmrg * Free context meta-op state. 4284a49301eSmrg * To be called once during context destruction. 4294a49301eSmrg */ 4304a49301eSmrgvoid 4313464ebd5Sriastradh_mesa_meta_free(struct gl_context *ctx) 4324a49301eSmrg{ 433af69d88dSmrg GET_CURRENT_CONTEXT(old_context); 434af69d88dSmrg _mesa_make_current(ctx, NULL, NULL); 43501e04c3fSmrg _mesa_meta_glsl_blit_cleanup(ctx, &ctx->Meta->Blit); 43601e04c3fSmrg meta_glsl_clear_cleanup(ctx, &ctx->Meta->Clear); 437a8bb7a65Smaya meta_copypix_cleanup(ctx, &ctx->Meta->CopyPix); 43801e04c3fSmrg _mesa_meta_glsl_generate_mipmap_cleanup(ctx, &ctx->Meta->Mipmap); 43901e04c3fSmrg cleanup_temp_texture(ctx, &ctx->Meta->TempTex); 44001e04c3fSmrg meta_decompress_cleanup(ctx, &ctx->Meta->Decompress); 44101e04c3fSmrg meta_drawpix_cleanup(ctx, &ctx->Meta->DrawPix); 4427ec681f3Smrg meta_drawtex_cleanup(ctx, &ctx->Meta->DrawTex); 4437ec681f3Smrg meta_bitmap_cleanup(ctx, &ctx->Meta->Bitmap); 4447ec681f3Smrg 445af69d88dSmrg if (old_context) 446af69d88dSmrg _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer); 447af69d88dSmrg else 448af69d88dSmrg _mesa_make_current(NULL, NULL, NULL); 449cdc920a0Smrg free(ctx->Meta); 4504a49301eSmrg ctx->Meta = NULL; 4514a49301eSmrg} 4524a49301eSmrg 4534a49301eSmrg 4544a49301eSmrg/** 4554a49301eSmrg * Enter meta state. This is like a light-weight version of glPushAttrib 4564a49301eSmrg * but it also resets most GL state back to default values. 4574a49301eSmrg * 458af69d88dSmrg * \param state bitmask of MESA_META_* flags indicating which attribute groups 4594a49301eSmrg * to save and reset to their defaults 4604a49301eSmrg */ 461af69d88dSmrgvoid 4623464ebd5Sriastradh_mesa_meta_begin(struct gl_context *ctx, GLbitfield state) 4634a49301eSmrg{ 4643464ebd5Sriastradh struct save_state *save; 4654a49301eSmrg 4663464ebd5Sriastradh /* hope MAX_META_OPS_DEPTH is large enough */ 4673464ebd5Sriastradh assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH); 4683464ebd5Sriastradh 4693464ebd5Sriastradh save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++]; 4703464ebd5Sriastradh memset(save, 0, sizeof(*save)); 4714a49301eSmrg save->SavedState = state; 4724a49301eSmrg 473af69d88dSmrg /* We always push into desktop GL mode and pop out at the end. No sense in 474af69d88dSmrg * writing our shaders varying based on the user's context choice, when 475af69d88dSmrg * Mesa can handle either. 476af69d88dSmrg */ 477af69d88dSmrg save->API = ctx->API; 478af69d88dSmrg ctx->API = API_OPENGL_COMPAT; 479af69d88dSmrg 48001e04c3fSmrg /* Mesa's extension helper functions use the current context's API to look up 48101e04c3fSmrg * the version required by an extension as a step in determining whether or 48201e04c3fSmrg * not it has been advertised. Since meta aims to only be restricted by the 48301e04c3fSmrg * driver capability (and not by whether or not an extension has been 48401e04c3fSmrg * advertised), set the helper functions' Version variable to a value that 48501e04c3fSmrg * will make the checks on the context API and version unconditionally pass. 48601e04c3fSmrg */ 48701e04c3fSmrg save->ExtensionsVersion = ctx->Extensions.Version; 48801e04c3fSmrg ctx->Extensions.Version = ~0; 48901e04c3fSmrg 490af69d88dSmrg /* Pausing transform feedback needs to be done early, or else we won't be 491af69d88dSmrg * able to change other state. 492af69d88dSmrg */ 493af69d88dSmrg save->TransformFeedbackNeedsResume = 494af69d88dSmrg _mesa_is_xfb_active_and_unpaused(ctx); 495af69d88dSmrg if (save->TransformFeedbackNeedsResume) 496af69d88dSmrg _mesa_PauseTransformFeedback(); 497af69d88dSmrg 498af69d88dSmrg /* After saving the current occlusion object, call EndQuery so that no 499af69d88dSmrg * occlusion querying will be active during the meta-operation. 500af69d88dSmrg */ 501af69d88dSmrg if (state & MESA_META_OCCLUSION_QUERY) { 502af69d88dSmrg save->CurrentOcclusionObject = ctx->Query.CurrentOcclusionObject; 503af69d88dSmrg if (save->CurrentOcclusionObject) 504af69d88dSmrg _mesa_EndQuery(save->CurrentOcclusionObject->Target); 505af69d88dSmrg } 506af69d88dSmrg 507af69d88dSmrg if (state & MESA_META_ALPHA_TEST) { 5084a49301eSmrg save->AlphaEnabled = ctx->Color.AlphaEnabled; 5093464ebd5Sriastradh save->AlphaFunc = ctx->Color.AlphaFunc; 5103464ebd5Sriastradh save->AlphaRef = ctx->Color.AlphaRef; 5114a49301eSmrg if (ctx->Color.AlphaEnabled) 5124a49301eSmrg _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE); 5134a49301eSmrg } 5144a49301eSmrg 515af69d88dSmrg if (state & MESA_META_BLEND) { 5164a49301eSmrg save->BlendEnabled = ctx->Color.BlendEnabled; 517cdc920a0Smrg if (ctx->Color.BlendEnabled) { 518cdc920a0Smrg if (ctx->Extensions.EXT_draw_buffers2) { 519cdc920a0Smrg GLuint i; 520cdc920a0Smrg for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 521cdc920a0Smrg _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE); 522cdc920a0Smrg } 523cdc920a0Smrg } 524cdc920a0Smrg else { 525cdc920a0Smrg _mesa_set_enable(ctx, GL_BLEND, GL_FALSE); 526cdc920a0Smrg } 527cdc920a0Smrg } 5284a49301eSmrg save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled; 5294a49301eSmrg if (ctx->Color.ColorLogicOpEnabled) 5304a49301eSmrg _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE); 5314a49301eSmrg } 5324a49301eSmrg 533af69d88dSmrg if (state & MESA_META_DITHER) { 534af69d88dSmrg save->DitherFlag = ctx->Color.DitherFlag; 535af69d88dSmrg _mesa_set_enable(ctx, GL_DITHER, GL_TRUE); 536af69d88dSmrg } 537af69d88dSmrg 53801e04c3fSmrg if (state & MESA_META_COLOR_MASK) 53901e04c3fSmrg save->ColorMask = ctx->Color.ColorMask; 5404a49301eSmrg 541af69d88dSmrg if (state & MESA_META_DEPTH_TEST) { 5424a49301eSmrg save->Depth = ctx->Depth; /* struct copy */ 5434a49301eSmrg if (ctx->Depth.Test) 5444a49301eSmrg _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); 5454a49301eSmrg } 5464a49301eSmrg 547af69d88dSmrg if (state & MESA_META_FOG) { 5484a49301eSmrg save->Fog = ctx->Fog.Enabled; 5494a49301eSmrg if (ctx->Fog.Enabled) 5504a49301eSmrg _mesa_set_enable(ctx, GL_FOG, GL_FALSE); 5514a49301eSmrg } 5524a49301eSmrg 553af69d88dSmrg if (state & MESA_META_PIXEL_STORE) { 5544a49301eSmrg save->Pack = ctx->Pack; 5554a49301eSmrg save->Unpack = ctx->Unpack; 5564a49301eSmrg ctx->Pack = ctx->DefaultPacking; 5574a49301eSmrg ctx->Unpack = ctx->DefaultPacking; 5584a49301eSmrg } 5594a49301eSmrg 560af69d88dSmrg if (state & MESA_META_PIXEL_TRANSFER) { 5614a49301eSmrg save->RedScale = ctx->Pixel.RedScale; 5624a49301eSmrg save->RedBias = ctx->Pixel.RedBias; 5634a49301eSmrg save->GreenScale = ctx->Pixel.GreenScale; 5644a49301eSmrg save->GreenBias = ctx->Pixel.GreenBias; 5654a49301eSmrg save->BlueScale = ctx->Pixel.BlueScale; 5664a49301eSmrg save->BlueBias = ctx->Pixel.BlueBias; 5674a49301eSmrg save->AlphaScale = ctx->Pixel.AlphaScale; 5684a49301eSmrg save->AlphaBias = ctx->Pixel.AlphaBias; 5694a49301eSmrg save->MapColorFlag = ctx->Pixel.MapColorFlag; 5704a49301eSmrg ctx->Pixel.RedScale = 1.0F; 5714a49301eSmrg ctx->Pixel.RedBias = 0.0F; 5724a49301eSmrg ctx->Pixel.GreenScale = 1.0F; 5734a49301eSmrg ctx->Pixel.GreenBias = 0.0F; 5744a49301eSmrg ctx->Pixel.BlueScale = 1.0F; 5754a49301eSmrg ctx->Pixel.BlueBias = 0.0F; 5764a49301eSmrg ctx->Pixel.AlphaScale = 1.0F; 5774a49301eSmrg ctx->Pixel.AlphaBias = 0.0F; 5784a49301eSmrg ctx->Pixel.MapColorFlag = GL_FALSE; 5794a49301eSmrg /* XXX more state */ 5804a49301eSmrg ctx->NewState |=_NEW_PIXEL; 5814a49301eSmrg } 5824a49301eSmrg 583af69d88dSmrg if (state & MESA_META_RASTERIZATION) { 5844a49301eSmrg save->FrontPolygonMode = ctx->Polygon.FrontMode; 5854a49301eSmrg save->BackPolygonMode = ctx->Polygon.BackMode; 5864a49301eSmrg save->PolygonOffset = ctx->Polygon.OffsetFill; 5874a49301eSmrg save->PolygonSmooth = ctx->Polygon.SmoothFlag; 5884a49301eSmrg save->PolygonStipple = ctx->Polygon.StippleFlag; 5894a49301eSmrg save->PolygonCull = ctx->Polygon.CullFlag; 5904a49301eSmrg _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); 5914a49301eSmrg _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); 5924a49301eSmrg _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); 5934a49301eSmrg _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); 5944a49301eSmrg _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); 5954a49301eSmrg } 5964a49301eSmrg 597af69d88dSmrg if (state & MESA_META_SCISSOR) { 5984a49301eSmrg save->Scissor = ctx->Scissor; /* struct copy */ 599cdc920a0Smrg _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE); 6004a49301eSmrg } 6014a49301eSmrg 602af69d88dSmrg if (state & MESA_META_SHADER) { 603af69d88dSmrg int i; 604af69d88dSmrg 6054a49301eSmrg if (ctx->Extensions.ARB_vertex_program) { 6064a49301eSmrg save->VertexProgramEnabled = ctx->VertexProgram.Enabled; 60701e04c3fSmrg _mesa_reference_program(ctx, &save->VertexProgram, 60801e04c3fSmrg ctx->VertexProgram.Current); 6094a49301eSmrg _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); 6104a49301eSmrg } 6114a49301eSmrg 6124a49301eSmrg if (ctx->Extensions.ARB_fragment_program) { 6134a49301eSmrg save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; 61401e04c3fSmrg _mesa_reference_program(ctx, &save->FragmentProgram, 61501e04c3fSmrg ctx->FragmentProgram.Current); 6164a49301eSmrg _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); 6174a49301eSmrg } 6184a49301eSmrg 619af69d88dSmrg if (ctx->Extensions.ATI_fragment_shader) { 620af69d88dSmrg save->ATIFragmentShaderEnabled = ctx->ATIFragmentShader.Enabled; 621af69d88dSmrg _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, GL_FALSE); 622af69d88dSmrg } 623af69d88dSmrg 624af69d88dSmrg if (ctx->Pipeline.Current) { 625af69d88dSmrg _mesa_reference_pipeline_object(ctx, &save->Pipeline, 626af69d88dSmrg ctx->Pipeline.Current); 627af69d88dSmrg _mesa_BindProgramPipeline(0); 628af69d88dSmrg } 629af69d88dSmrg 630af69d88dSmrg /* Save the shader state from ctx->Shader (instead of ctx->_Shader) so 631af69d88dSmrg * that we don't have to worry about the current pipeline state. 632af69d88dSmrg */ 63301e04c3fSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 63401e04c3fSmrg _mesa_reference_program(ctx, &save->Program[i], 63501e04c3fSmrg ctx->Shader.CurrentProgram[i]); 6364a49301eSmrg } 637af69d88dSmrg _mesa_reference_shader_program(ctx, &save->ActiveShader, 638af69d88dSmrg ctx->Shader.ActiveProgram); 639af69d88dSmrg 640af69d88dSmrg _mesa_UseProgram(0); 6414a49301eSmrg } 6424a49301eSmrg 643af69d88dSmrg if (state & MESA_META_STENCIL_TEST) { 6444a49301eSmrg save->Stencil = ctx->Stencil; /* struct copy */ 6454a49301eSmrg if (ctx->Stencil.Enabled) 6464a49301eSmrg _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE); 6474a49301eSmrg /* NOTE: other stencil state not reset */ 6484a49301eSmrg } 6494a49301eSmrg 650af69d88dSmrg if (state & MESA_META_TEXTURE) { 6514a49301eSmrg GLuint u, tgt; 6524a49301eSmrg 6534a49301eSmrg save->ActiveUnit = ctx->Texture.CurrentUnit; 65401e04c3fSmrg save->EnvMode = ctx->Texture.FixedFuncUnit[0].EnvMode; 6554a49301eSmrg 6564a49301eSmrg /* Disable all texture units */ 6574a49301eSmrg for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 65801e04c3fSmrg save->TexEnabled[u] = ctx->Texture.FixedFuncUnit[u].Enabled; 65901e04c3fSmrg save->TexGenEnabled[u] = ctx->Texture.FixedFuncUnit[u].TexGenEnabled; 66001e04c3fSmrg if (ctx->Texture.FixedFuncUnit[u].Enabled || 66101e04c3fSmrg ctx->Texture.FixedFuncUnit[u].TexGenEnabled) { 662af69d88dSmrg _mesa_ActiveTexture(GL_TEXTURE0 + u); 6634a49301eSmrg _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); 6643464ebd5Sriastradh if (ctx->Extensions.ARB_texture_cube_map) 6653464ebd5Sriastradh _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); 666af69d88dSmrg 667af69d88dSmrg _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); 668af69d88dSmrg _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); 669af69d88dSmrg if (ctx->Extensions.NV_texture_rectangle) 670af69d88dSmrg _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); 6714a49301eSmrg _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); 6724a49301eSmrg _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); 6734a49301eSmrg _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); 6744a49301eSmrg _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); 6754a49301eSmrg } 6764a49301eSmrg } 6774a49301eSmrg 6784a49301eSmrg /* save current texture objects for unit[0] only */ 6794a49301eSmrg for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 6804a49301eSmrg _mesa_reference_texobj(&save->CurrentTexture[tgt], 6814a49301eSmrg ctx->Texture.Unit[0].CurrentTex[tgt]); 6824a49301eSmrg } 6834a49301eSmrg 6844a49301eSmrg /* set defaults for unit[0] */ 685af69d88dSmrg _mesa_ActiveTexture(GL_TEXTURE0); 6864a49301eSmrg _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 6874a49301eSmrg } 6884a49301eSmrg 689af69d88dSmrg if (state & MESA_META_TRANSFORM) { 690cdc920a0Smrg memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m, 691cdc920a0Smrg 16 * sizeof(GLfloat)); 692cdc920a0Smrg memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m, 693cdc920a0Smrg 16 * sizeof(GLfloat)); 694cdc920a0Smrg memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m, 695cdc920a0Smrg 16 * sizeof(GLfloat)); 6967ec681f3Smrg 6974a49301eSmrg /* set 1:1 vertex:pixel coordinate transform */ 6987ec681f3Smrg _mesa_load_identity_matrix(ctx, &ctx->ModelviewMatrixStack); 6997ec681f3Smrg _mesa_load_identity_matrix(ctx, &ctx->TextureMatrixStack[0]); 7007ec681f3Smrg 7017ec681f3Smrg /* _math_float_ortho with width = 0 or height = 0 will have a divide by 7027ec681f3Smrg * zero. This can occur when there is no draw buffer. 703af69d88dSmrg */ 7047ec681f3Smrg if (ctx->DrawBuffer->Width != 0 && ctx->DrawBuffer->Height != 0) { 7057ec681f3Smrg float m[16]; 7067ec681f3Smrg 7077ec681f3Smrg _math_float_ortho(m, 7087ec681f3Smrg 0.0f, (float) ctx->DrawBuffer->Width, 7097ec681f3Smrg 0.0f, (float) ctx->DrawBuffer->Height, 7107ec681f3Smrg -1.0f, 1.0f); 7117ec681f3Smrg _mesa_load_matrix(ctx, &ctx->ProjectionMatrixStack, m); 7127ec681f3Smrg } else { 7137ec681f3Smrg _mesa_load_identity_matrix(ctx, &ctx->ProjectionMatrixStack); 7147ec681f3Smrg } 71501e04c3fSmrg 71601e04c3fSmrg if (ctx->Extensions.ARB_clip_control) { 71701e04c3fSmrg save->ClipOrigin = ctx->Transform.ClipOrigin; 71801e04c3fSmrg save->ClipDepthMode = ctx->Transform.ClipDepthMode; 71901e04c3fSmrg _mesa_ClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE); 72001e04c3fSmrg } 721af69d88dSmrg } 722af69d88dSmrg 723af69d88dSmrg if (state & MESA_META_CLIP) { 72401e04c3fSmrg GLbitfield mask; 7254a49301eSmrg save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled; 72601e04c3fSmrg mask = ctx->Transform.ClipPlanesEnabled; 72701e04c3fSmrg while (mask) { 72801e04c3fSmrg const int i = u_bit_scan(&mask); 72901e04c3fSmrg _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE); 7304a49301eSmrg } 7314a49301eSmrg } 7324a49301eSmrg 733af69d88dSmrg if (state & MESA_META_VERTEX) { 7344a49301eSmrg /* save vertex array object state */ 735af69d88dSmrg _mesa_reference_vao(ctx, &save->VAO, 736af69d88dSmrg ctx->Array.VAO); 7374a49301eSmrg /* set some default state? */ 7384a49301eSmrg } 7394a49301eSmrg 740af69d88dSmrg if (state & MESA_META_VIEWPORT) { 7414a49301eSmrg /* save viewport state */ 742af69d88dSmrg save->ViewportX = ctx->ViewportArray[0].X; 743af69d88dSmrg save->ViewportY = ctx->ViewportArray[0].Y; 744af69d88dSmrg save->ViewportW = ctx->ViewportArray[0].Width; 745af69d88dSmrg save->ViewportH = ctx->ViewportArray[0].Height; 7464a49301eSmrg /* set viewport to match window size */ 747af69d88dSmrg if (ctx->ViewportArray[0].X != 0 || 748af69d88dSmrg ctx->ViewportArray[0].Y != 0 || 749af69d88dSmrg ctx->ViewportArray[0].Width != (float) ctx->DrawBuffer->Width || 750af69d88dSmrg ctx->ViewportArray[0].Height != (float) ctx->DrawBuffer->Height) { 751af69d88dSmrg _mesa_set_viewport(ctx, 0, 0, 0, 7524a49301eSmrg ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); 7534a49301eSmrg } 7544a49301eSmrg /* save depth range state */ 755af69d88dSmrg save->DepthNear = ctx->ViewportArray[0].Near; 756af69d88dSmrg save->DepthFar = ctx->ViewportArray[0].Far; 7574a49301eSmrg /* set depth range to default */ 75801e04c3fSmrg _mesa_set_depth_range(ctx, 0, 0.0, 1.0); 7594a49301eSmrg } 7604a49301eSmrg 761af69d88dSmrg if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { 7623464ebd5Sriastradh save->ClampFragmentColor = ctx->Color.ClampFragmentColor; 7633464ebd5Sriastradh 7643464ebd5Sriastradh /* Generally in here we want to do clamping according to whether 7653464ebd5Sriastradh * it's for the pixel path (ClampFragmentColor is GL_TRUE), 7663464ebd5Sriastradh * regardless of the internal implementation of the metaops. 7673464ebd5Sriastradh */ 768af69d88dSmrg if (ctx->Color.ClampFragmentColor != GL_TRUE && 769af69d88dSmrg ctx->Extensions.ARB_color_buffer_float) 77001e04c3fSmrg _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 7713464ebd5Sriastradh } 7723464ebd5Sriastradh 773af69d88dSmrg if (state & MESA_META_CLAMP_VERTEX_COLOR) { 7743464ebd5Sriastradh save->ClampVertexColor = ctx->Light.ClampVertexColor; 7753464ebd5Sriastradh 7763464ebd5Sriastradh /* Generally in here we never want vertex color clamping -- 7773464ebd5Sriastradh * result clamping is only dependent on fragment clamping. 7783464ebd5Sriastradh */ 779af69d88dSmrg if (ctx->Extensions.ARB_color_buffer_float) 780af69d88dSmrg _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE); 7813464ebd5Sriastradh } 7823464ebd5Sriastradh 783af69d88dSmrg if (state & MESA_META_CONDITIONAL_RENDER) { 7843464ebd5Sriastradh save->CondRenderQuery = ctx->Query.CondRenderQuery; 7853464ebd5Sriastradh save->CondRenderMode = ctx->Query.CondRenderMode; 7863464ebd5Sriastradh 7873464ebd5Sriastradh if (ctx->Query.CondRenderQuery) 78801e04c3fSmrg _mesa_EndConditionalRender(); 7893464ebd5Sriastradh } 7903464ebd5Sriastradh 791af69d88dSmrg if (state & MESA_META_SELECT_FEEDBACK) { 792af69d88dSmrg save->RenderMode = ctx->RenderMode; 793af69d88dSmrg if (ctx->RenderMode == GL_SELECT) { 79401e04c3fSmrg save->Select = ctx->Select; /* struct copy */ 79501e04c3fSmrg _mesa_RenderMode(GL_RENDER); 796af69d88dSmrg } else if (ctx->RenderMode == GL_FEEDBACK) { 79701e04c3fSmrg save->Feedback = ctx->Feedback; /* struct copy */ 79801e04c3fSmrg _mesa_RenderMode(GL_RENDER); 799af69d88dSmrg } 800af69d88dSmrg } 801af69d88dSmrg 802af69d88dSmrg if (state & MESA_META_MULTISAMPLE) { 803af69d88dSmrg save->Multisample = ctx->Multisample; /* struct copy */ 804af69d88dSmrg 805af69d88dSmrg if (ctx->Multisample.Enabled) 806af69d88dSmrg _mesa_set_multisample(ctx, GL_FALSE); 807af69d88dSmrg if (ctx->Multisample.SampleCoverage) 808af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, GL_FALSE); 809af69d88dSmrg if (ctx->Multisample.SampleAlphaToCoverage) 810af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_FALSE); 811af69d88dSmrg if (ctx->Multisample.SampleAlphaToOne) 812af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, GL_FALSE); 813af69d88dSmrg if (ctx->Multisample.SampleShading) 814af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_FALSE); 815af69d88dSmrg if (ctx->Multisample.SampleMask) 816af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_MASK, GL_FALSE); 817af69d88dSmrg } 818af69d88dSmrg 819af69d88dSmrg if (state & MESA_META_FRAMEBUFFER_SRGB) { 820af69d88dSmrg save->sRGBEnabled = ctx->Color.sRGBEnabled; 821af69d88dSmrg if (ctx->Color.sRGBEnabled) 822af69d88dSmrg _mesa_set_framebuffer_srgb(ctx, GL_FALSE); 823af69d88dSmrg } 824af69d88dSmrg 825af69d88dSmrg if (state & MESA_META_DRAW_BUFFERS) { 826af69d88dSmrg struct gl_framebuffer *fb = ctx->DrawBuffer; 827af69d88dSmrg memcpy(save->ColorDrawBuffers, fb->ColorDrawBuffer, 828af69d88dSmrg sizeof(save->ColorDrawBuffers)); 829af69d88dSmrg } 830af69d88dSmrg 8314a49301eSmrg /* misc */ 8324a49301eSmrg { 8334a49301eSmrg save->Lighting = ctx->Light.Enabled; 8344a49301eSmrg if (ctx->Light.Enabled) 8354a49301eSmrg _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE); 836af69d88dSmrg save->RasterDiscard = ctx->RasterDiscard; 837af69d88dSmrg if (ctx->RasterDiscard) 838af69d88dSmrg _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE); 839af69d88dSmrg 84001e04c3fSmrg _mesa_reference_framebuffer(&save->DrawBuffer, ctx->DrawBuffer); 84101e04c3fSmrg _mesa_reference_framebuffer(&save->ReadBuffer, ctx->ReadBuffer); 8424a49301eSmrg } 8434a49301eSmrg} 8444a49301eSmrg 8454a49301eSmrg 8464a49301eSmrg/** 8474a49301eSmrg * Leave meta state. This is like a light-weight version of glPopAttrib(). 8484a49301eSmrg */ 849af69d88dSmrgvoid 8503464ebd5Sriastradh_mesa_meta_end(struct gl_context *ctx) 8514a49301eSmrg{ 85201e04c3fSmrg assert(ctx->Meta->SaveStackDepth > 0); 85301e04c3fSmrg 854af69d88dSmrg struct save_state *save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth - 1]; 8554a49301eSmrg const GLbitfield state = save->SavedState; 856af69d88dSmrg int i; 8574a49301eSmrg 85801e04c3fSmrg /* Grab the result of the old occlusion query before starting it again. The 85901e04c3fSmrg * old result is added to the result of the new query so the driver will 86001e04c3fSmrg * continue adding where it left off. */ 861af69d88dSmrg if (state & MESA_META_OCCLUSION_QUERY) { 862af69d88dSmrg if (save->CurrentOcclusionObject) { 86301e04c3fSmrg struct gl_query_object *q = save->CurrentOcclusionObject; 86401e04c3fSmrg GLuint64EXT result; 86501e04c3fSmrg if (!q->Ready) 86601e04c3fSmrg ctx->Driver.WaitQuery(ctx, q); 86701e04c3fSmrg result = q->Result; 86801e04c3fSmrg _mesa_BeginQuery(q->Target, q->Id); 86901e04c3fSmrg ctx->Query.CurrentOcclusionObject->Result += result; 870af69d88dSmrg } 871af69d88dSmrg } 872af69d88dSmrg 873af69d88dSmrg if (state & MESA_META_ALPHA_TEST) { 8744a49301eSmrg if (ctx->Color.AlphaEnabled != save->AlphaEnabled) 8754a49301eSmrg _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled); 8763464ebd5Sriastradh _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef); 8774a49301eSmrg } 8784a49301eSmrg 879af69d88dSmrg if (state & MESA_META_BLEND) { 880cdc920a0Smrg if (ctx->Color.BlendEnabled != save->BlendEnabled) { 881cdc920a0Smrg if (ctx->Extensions.EXT_draw_buffers2) { 882cdc920a0Smrg GLuint i; 883cdc920a0Smrg for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 884cdc920a0Smrg _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1); 885cdc920a0Smrg } 886cdc920a0Smrg } 887cdc920a0Smrg else { 888cdc920a0Smrg _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1)); 889cdc920a0Smrg } 890cdc920a0Smrg } 8914a49301eSmrg if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled) 8924a49301eSmrg _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled); 8934a49301eSmrg } 8944a49301eSmrg 895af69d88dSmrg if (state & MESA_META_DITHER) 896af69d88dSmrg _mesa_set_enable(ctx, GL_DITHER, save->DitherFlag); 897af69d88dSmrg 898af69d88dSmrg if (state & MESA_META_COLOR_MASK) { 899cdc920a0Smrg GLuint i; 900cdc920a0Smrg for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 90101e04c3fSmrg if (GET_COLORMASK(ctx->Color.ColorMask, i) != 90201e04c3fSmrg GET_COLORMASK(save->ColorMask, i)) { 903cdc920a0Smrg if (i == 0) { 90401e04c3fSmrg _mesa_ColorMask(GET_COLORMASK_BIT(save->ColorMask, i, 0), 90501e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 1), 90601e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 2), 90701e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 3)); 908cdc920a0Smrg } 909cdc920a0Smrg else { 910af69d88dSmrg _mesa_ColorMaski(i, 91101e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 0), 91201e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 1), 91301e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 2), 91401e04c3fSmrg GET_COLORMASK_BIT(save->ColorMask, i, 3)); 915cdc920a0Smrg } 916cdc920a0Smrg } 917cdc920a0Smrg } 9184a49301eSmrg } 9194a49301eSmrg 920af69d88dSmrg if (state & MESA_META_DEPTH_TEST) { 9214a49301eSmrg if (ctx->Depth.Test != save->Depth.Test) 9224a49301eSmrg _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test); 9234a49301eSmrg _mesa_DepthFunc(save->Depth.Func); 9244a49301eSmrg _mesa_DepthMask(save->Depth.Mask); 9254a49301eSmrg } 9264a49301eSmrg 927af69d88dSmrg if (state & MESA_META_FOG) { 9284a49301eSmrg _mesa_set_enable(ctx, GL_FOG, save->Fog); 9294a49301eSmrg } 9304a49301eSmrg 931af69d88dSmrg if (state & MESA_META_PIXEL_STORE) { 9324a49301eSmrg ctx->Pack = save->Pack; 9334a49301eSmrg ctx->Unpack = save->Unpack; 9344a49301eSmrg } 9354a49301eSmrg 936af69d88dSmrg if (state & MESA_META_PIXEL_TRANSFER) { 9374a49301eSmrg ctx->Pixel.RedScale = save->RedScale; 9384a49301eSmrg ctx->Pixel.RedBias = save->RedBias; 9394a49301eSmrg ctx->Pixel.GreenScale = save->GreenScale; 9404a49301eSmrg ctx->Pixel.GreenBias = save->GreenBias; 9414a49301eSmrg ctx->Pixel.BlueScale = save->BlueScale; 9424a49301eSmrg ctx->Pixel.BlueBias = save->BlueBias; 9434a49301eSmrg ctx->Pixel.AlphaScale = save->AlphaScale; 9444a49301eSmrg ctx->Pixel.AlphaBias = save->AlphaBias; 9454a49301eSmrg ctx->Pixel.MapColorFlag = save->MapColorFlag; 9464a49301eSmrg /* XXX more state */ 9474a49301eSmrg ctx->NewState |=_NEW_PIXEL; 9484a49301eSmrg } 9494a49301eSmrg 950af69d88dSmrg if (state & MESA_META_RASTERIZATION) { 9514a49301eSmrg _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); 9524a49301eSmrg _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); 9534a49301eSmrg _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); 9544a49301eSmrg _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); 955af69d88dSmrg _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); 9564a49301eSmrg _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); 9574a49301eSmrg } 9584a49301eSmrg 959af69d88dSmrg if (state & MESA_META_SCISSOR) { 960af69d88dSmrg unsigned i; 961af69d88dSmrg 962af69d88dSmrg for (i = 0; i < ctx->Const.MaxViewports; i++) { 963af69d88dSmrg _mesa_set_scissor(ctx, i, 964af69d88dSmrg save->Scissor.ScissorArray[i].X, 965af69d88dSmrg save->Scissor.ScissorArray[i].Y, 966af69d88dSmrg save->Scissor.ScissorArray[i].Width, 967af69d88dSmrg save->Scissor.ScissorArray[i].Height); 968af69d88dSmrg _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i, 969af69d88dSmrg (save->Scissor.EnableFlags >> i) & 1); 970af69d88dSmrg } 9714a49301eSmrg } 9724a49301eSmrg 973af69d88dSmrg if (state & MESA_META_SHADER) { 974af69d88dSmrg bool any_shader; 975af69d88dSmrg 9764a49301eSmrg if (ctx->Extensions.ARB_vertex_program) { 9774a49301eSmrg _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, 9784a49301eSmrg save->VertexProgramEnabled); 97901e04c3fSmrg _mesa_reference_program(ctx, &ctx->VertexProgram.Current, 98001e04c3fSmrg save->VertexProgram); 98101e04c3fSmrg _mesa_reference_program(ctx, &save->VertexProgram, NULL); 9824a49301eSmrg } 9834a49301eSmrg 9844a49301eSmrg if (ctx->Extensions.ARB_fragment_program) { 9854a49301eSmrg _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, 9864a49301eSmrg save->FragmentProgramEnabled); 98701e04c3fSmrg _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, 98801e04c3fSmrg save->FragmentProgram); 98901e04c3fSmrg _mesa_reference_program(ctx, &save->FragmentProgram, NULL); 9904a49301eSmrg } 9914a49301eSmrg 992af69d88dSmrg if (ctx->Extensions.ATI_fragment_shader) { 993af69d88dSmrg _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, 994af69d88dSmrg save->ATIFragmentShaderEnabled); 995af69d88dSmrg } 996af69d88dSmrg 997af69d88dSmrg any_shader = false; 99801e04c3fSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 99901e04c3fSmrg /* It is safe to call _mesa_use_program even if the extension 1000af69d88dSmrg * necessary for that program state is not supported. In that case, 1001af69d88dSmrg * the saved program object must be NULL and the currently bound 100201e04c3fSmrg * program object must be NULL. _mesa_use_program is a no-op 1003af69d88dSmrg * in that case. 1004af69d88dSmrg */ 100501e04c3fSmrg _mesa_use_program(ctx, i, NULL, save->Program[i], &ctx->Shader); 10063464ebd5Sriastradh 1007af69d88dSmrg /* Do this *before* killing the reference. :) 1008af69d88dSmrg */ 100901e04c3fSmrg if (save->Program[i] != NULL) 1010af69d88dSmrg any_shader = true; 10113464ebd5Sriastradh 101201e04c3fSmrg _mesa_reference_program(ctx, &save->Program[i], NULL); 1013af69d88dSmrg } 10143464ebd5Sriastradh 10153464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, 1016af69d88dSmrg save->ActiveShader); 1017af69d88dSmrg _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL); 1018af69d88dSmrg 1019af69d88dSmrg /* If there were any stages set with programs, use ctx->Shader as the 1020af69d88dSmrg * current shader state. Otherwise, use Pipeline.Default. The pipeline 1021af69d88dSmrg * hasn't been restored yet, and that may modify ctx->_Shader further. 1022af69d88dSmrg */ 1023af69d88dSmrg if (any_shader) 1024af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, 1025af69d88dSmrg &ctx->Shader); 1026af69d88dSmrg else 1027af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, 1028af69d88dSmrg ctx->Pipeline.Default); 1029af69d88dSmrg 1030af69d88dSmrg if (save->Pipeline) { 1031af69d88dSmrg _mesa_bind_pipeline(ctx, save->Pipeline); 1032af69d88dSmrg 1033af69d88dSmrg _mesa_reference_pipeline_object(ctx, &save->Pipeline, NULL); 1034af69d88dSmrg } 103501e04c3fSmrg 103601e04c3fSmrg _mesa_update_vertex_processing_mode(ctx); 10377ec681f3Smrg _mesa_update_valid_to_render_state(ctx); 10384a49301eSmrg } 10394a49301eSmrg 1040af69d88dSmrg if (state & MESA_META_STENCIL_TEST) { 10414a49301eSmrg const struct gl_stencil_attrib *stencil = &save->Stencil; 10424a49301eSmrg 10434a49301eSmrg _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); 10444a49301eSmrg _mesa_ClearStencil(stencil->Clear); 10454a49301eSmrg if (ctx->Extensions.EXT_stencil_two_side) { 10464a49301eSmrg _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, 10474a49301eSmrg stencil->TestTwoSide); 10484a49301eSmrg _mesa_ActiveStencilFaceEXT(stencil->ActiveFace 10494a49301eSmrg ? GL_BACK : GL_FRONT); 10504a49301eSmrg } 10514a49301eSmrg /* front state */ 10524a49301eSmrg _mesa_StencilFuncSeparate(GL_FRONT, 10534a49301eSmrg stencil->Function[0], 10544a49301eSmrg stencil->Ref[0], 10554a49301eSmrg stencil->ValueMask[0]); 10564a49301eSmrg _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); 10574a49301eSmrg _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], 10584a49301eSmrg stencil->ZFailFunc[0], 10594a49301eSmrg stencil->ZPassFunc[0]); 10604a49301eSmrg /* back state */ 10614a49301eSmrg _mesa_StencilFuncSeparate(GL_BACK, 10624a49301eSmrg stencil->Function[1], 10634a49301eSmrg stencil->Ref[1], 10644a49301eSmrg stencil->ValueMask[1]); 10654a49301eSmrg _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); 10664a49301eSmrg _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], 10674a49301eSmrg stencil->ZFailFunc[1], 10684a49301eSmrg stencil->ZPassFunc[1]); 10694a49301eSmrg } 10704a49301eSmrg 1071af69d88dSmrg if (state & MESA_META_TEXTURE) { 10724a49301eSmrg GLuint u, tgt; 10734a49301eSmrg 107401e04c3fSmrg assert(ctx->Texture.CurrentUnit == 0); 10754a49301eSmrg 10764a49301eSmrg /* restore texenv for unit[0] */ 10774a49301eSmrg _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); 10784a49301eSmrg 10794a49301eSmrg /* restore texture objects for unit[0] only */ 10804a49301eSmrg for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 108101e04c3fSmrg if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) { 10827ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE, GL_TEXTURE_BIT); 108301e04c3fSmrg _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], 108401e04c3fSmrg save->CurrentTexture[tgt]); 108501e04c3fSmrg } 10863464ebd5Sriastradh _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); 10874a49301eSmrg } 10884a49301eSmrg 1089af69d88dSmrg /* Restore fixed function texture enables, texgen */ 10904a49301eSmrg for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 109101e04c3fSmrg if (ctx->Texture.FixedFuncUnit[u].Enabled != save->TexEnabled[u]) { 10927ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE, GL_TEXTURE_BIT); 109301e04c3fSmrg ctx->Texture.FixedFuncUnit[u].Enabled = save->TexEnabled[u]; 10944a49301eSmrg } 10954a49301eSmrg 109601e04c3fSmrg if (ctx->Texture.FixedFuncUnit[u].TexGenEnabled != save->TexGenEnabled[u]) { 10977ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE, GL_TEXTURE_BIT); 109801e04c3fSmrg ctx->Texture.FixedFuncUnit[u].TexGenEnabled = save->TexGenEnabled[u]; 10994a49301eSmrg } 11004a49301eSmrg } 11014a49301eSmrg 11024a49301eSmrg /* restore current unit state */ 1103af69d88dSmrg _mesa_ActiveTexture(GL_TEXTURE0 + save->ActiveUnit); 11044a49301eSmrg } 11054a49301eSmrg 1106af69d88dSmrg if (state & MESA_META_TRANSFORM) { 11077ec681f3Smrg _mesa_load_matrix(ctx, &ctx->ModelviewMatrixStack, save->ModelviewMatrix); 11087ec681f3Smrg _mesa_load_matrix(ctx, &ctx->ProjectionMatrixStack, save->ProjectionMatrix); 11097ec681f3Smrg _mesa_load_matrix(ctx, &ctx->TextureMatrixStack[0], save->TextureMatrix); 111001e04c3fSmrg 111101e04c3fSmrg if (ctx->Extensions.ARB_clip_control) 111201e04c3fSmrg _mesa_ClipControl(save->ClipOrigin, save->ClipDepthMode); 1113af69d88dSmrg } 11144a49301eSmrg 1115af69d88dSmrg if (state & MESA_META_CLIP) { 111601e04c3fSmrg GLbitfield mask = save->ClipPlanesEnabled; 111701e04c3fSmrg while (mask) { 111801e04c3fSmrg const int i = u_bit_scan(&mask); 111901e04c3fSmrg _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); 11204a49301eSmrg } 11214a49301eSmrg } 11224a49301eSmrg 1123af69d88dSmrg if (state & MESA_META_VERTEX) { 11244a49301eSmrg /* restore vertex array object */ 1125af69d88dSmrg _mesa_BindVertexArray(save->VAO->Name); 1126af69d88dSmrg _mesa_reference_vao(ctx, &save->VAO, NULL); 11274a49301eSmrg } 11284a49301eSmrg 1129af69d88dSmrg if (state & MESA_META_VIEWPORT) { 1130af69d88dSmrg if (save->ViewportX != ctx->ViewportArray[0].X || 1131af69d88dSmrg save->ViewportY != ctx->ViewportArray[0].Y || 1132af69d88dSmrg save->ViewportW != ctx->ViewportArray[0].Width || 1133af69d88dSmrg save->ViewportH != ctx->ViewportArray[0].Height) { 1134af69d88dSmrg _mesa_set_viewport(ctx, 0, save->ViewportX, save->ViewportY, 11354a49301eSmrg save->ViewportW, save->ViewportH); 11364a49301eSmrg } 113701e04c3fSmrg _mesa_set_depth_range(ctx, 0, save->DepthNear, save->DepthFar); 11384a49301eSmrg } 11394a49301eSmrg 1140af69d88dSmrg if (state & MESA_META_CLAMP_FRAGMENT_COLOR && 1141af69d88dSmrg ctx->Extensions.ARB_color_buffer_float) { 1142af69d88dSmrg _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor); 11433464ebd5Sriastradh } 11443464ebd5Sriastradh 1145af69d88dSmrg if (state & MESA_META_CLAMP_VERTEX_COLOR && 1146af69d88dSmrg ctx->Extensions.ARB_color_buffer_float) { 1147af69d88dSmrg _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor); 11483464ebd5Sriastradh } 11493464ebd5Sriastradh 1150af69d88dSmrg if (state & MESA_META_CONDITIONAL_RENDER) { 11513464ebd5Sriastradh if (save->CondRenderQuery) 115201e04c3fSmrg _mesa_BeginConditionalRender(save->CondRenderQuery->Id, 115301e04c3fSmrg save->CondRenderMode); 11543464ebd5Sriastradh } 11553464ebd5Sriastradh 1156af69d88dSmrg if (state & MESA_META_SELECT_FEEDBACK) { 1157af69d88dSmrg if (save->RenderMode == GL_SELECT) { 115801e04c3fSmrg _mesa_RenderMode(GL_SELECT); 115901e04c3fSmrg ctx->Select = save->Select; 1160af69d88dSmrg } else if (save->RenderMode == GL_FEEDBACK) { 116101e04c3fSmrg _mesa_RenderMode(GL_FEEDBACK); 116201e04c3fSmrg ctx->Feedback = save->Feedback; 1163af69d88dSmrg } 1164af69d88dSmrg } 1165af69d88dSmrg 1166af69d88dSmrg if (state & MESA_META_MULTISAMPLE) { 1167af69d88dSmrg struct gl_multisample_attrib *ctx_ms = &ctx->Multisample; 1168af69d88dSmrg struct gl_multisample_attrib *save_ms = &save->Multisample; 1169af69d88dSmrg 1170af69d88dSmrg if (ctx_ms->Enabled != save_ms->Enabled) 1171af69d88dSmrg _mesa_set_multisample(ctx, save_ms->Enabled); 1172af69d88dSmrg if (ctx_ms->SampleCoverage != save_ms->SampleCoverage) 1173af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, save_ms->SampleCoverage); 1174af69d88dSmrg if (ctx_ms->SampleAlphaToCoverage != save_ms->SampleAlphaToCoverage) 1175af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, save_ms->SampleAlphaToCoverage); 1176af69d88dSmrg if (ctx_ms->SampleAlphaToOne != save_ms->SampleAlphaToOne) 1177af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, save_ms->SampleAlphaToOne); 1178af69d88dSmrg if (ctx_ms->SampleCoverageValue != save_ms->SampleCoverageValue || 1179af69d88dSmrg ctx_ms->SampleCoverageInvert != save_ms->SampleCoverageInvert) { 1180af69d88dSmrg _mesa_SampleCoverage(save_ms->SampleCoverageValue, 1181af69d88dSmrg save_ms->SampleCoverageInvert); 1182af69d88dSmrg } 1183af69d88dSmrg if (ctx_ms->SampleShading != save_ms->SampleShading) 1184af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_SHADING, save_ms->SampleShading); 1185af69d88dSmrg if (ctx_ms->SampleMask != save_ms->SampleMask) 1186af69d88dSmrg _mesa_set_enable(ctx, GL_SAMPLE_MASK, save_ms->SampleMask); 1187af69d88dSmrg if (ctx_ms->SampleMaskValue != save_ms->SampleMaskValue) 1188af69d88dSmrg _mesa_SampleMaski(0, save_ms->SampleMaskValue); 1189af69d88dSmrg if (ctx_ms->MinSampleShadingValue != save_ms->MinSampleShadingValue) 1190af69d88dSmrg _mesa_MinSampleShading(save_ms->MinSampleShadingValue); 1191af69d88dSmrg } 1192af69d88dSmrg 1193af69d88dSmrg if (state & MESA_META_FRAMEBUFFER_SRGB) { 1194af69d88dSmrg if (ctx->Color.sRGBEnabled != save->sRGBEnabled) 1195af69d88dSmrg _mesa_set_framebuffer_srgb(ctx, save->sRGBEnabled); 1196af69d88dSmrg } 1197af69d88dSmrg 11984a49301eSmrg /* misc */ 11994a49301eSmrg if (save->Lighting) { 12004a49301eSmrg _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); 12014a49301eSmrg } 1202af69d88dSmrg if (save->RasterDiscard) { 1203af69d88dSmrg _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE); 1204af69d88dSmrg } 1205af69d88dSmrg if (save->TransformFeedbackNeedsResume) 1206af69d88dSmrg _mesa_ResumeTransformFeedback(); 1207af69d88dSmrg 120801e04c3fSmrg _mesa_bind_framebuffers(ctx, save->DrawBuffer, save->ReadBuffer); 120901e04c3fSmrg _mesa_reference_framebuffer(&save->DrawBuffer, NULL); 121001e04c3fSmrg _mesa_reference_framebuffer(&save->ReadBuffer, NULL); 1211af69d88dSmrg 1212af69d88dSmrg if (state & MESA_META_DRAW_BUFFERS) { 121301e04c3fSmrg _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers, 121401e04c3fSmrg save->ColorDrawBuffers, NULL); 1215af69d88dSmrg } 1216af69d88dSmrg 1217af69d88dSmrg ctx->Meta->SaveStackDepth--; 1218af69d88dSmrg 1219af69d88dSmrg ctx->API = save->API; 122001e04c3fSmrg ctx->Extensions.Version = save->ExtensionsVersion; 12214a49301eSmrg} 12224a49301eSmrg 12234a49301eSmrg 1224cdc920a0Smrg/** 1225cdc920a0Smrg * Convert Z from a normalized value in the range [0, 1] to an object-space 1226cdc920a0Smrg * Z coordinate in [-1, +1] so that drawing at the new Z position with the 1227cdc920a0Smrg * default/identity ortho projection results in the original Z value. 1228cdc920a0Smrg * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z 1229cdc920a0Smrg * value comes from the clear value or raster position. 1230cdc920a0Smrg */ 123101e04c3fSmrgstatic inline GLfloat 1232cdc920a0Smrginvert_z(GLfloat normZ) 1233cdc920a0Smrg{ 1234af69d88dSmrg GLfloat objZ = 1.0f - 2.0f * normZ; 1235cdc920a0Smrg return objZ; 1236cdc920a0Smrg} 1237cdc920a0Smrg 1238cdc920a0Smrg 12394a49301eSmrg/** 12404a49301eSmrg * One-time init for a temp_texture object. 12414a49301eSmrg * Choose tex target, compute max tex size, etc. 12424a49301eSmrg */ 12434a49301eSmrgstatic void 12443464ebd5Sriastradhinit_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 12454a49301eSmrg{ 12464a49301eSmrg /* prefer texture rectangle */ 1247af69d88dSmrg if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle) { 12484a49301eSmrg tex->Target = GL_TEXTURE_RECTANGLE; 12494a49301eSmrg tex->MaxSize = ctx->Const.MaxTextureRectSize; 12504a49301eSmrg tex->NPOT = GL_TRUE; 12514a49301eSmrg } 12524a49301eSmrg else { 12534a49301eSmrg /* use 2D texture, NPOT if possible */ 12544a49301eSmrg tex->Target = GL_TEXTURE_2D; 12557ec681f3Smrg tex->MaxSize = ctx->Const.MaxTextureSize; 12564a49301eSmrg tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two; 12574a49301eSmrg } 12584a49301eSmrg tex->MinSize = 16; /* 16 x 16 at least */ 12594a49301eSmrg assert(tex->MaxSize > 0); 12604a49301eSmrg 126101e04c3fSmrg tex->tex_obj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, tex->Target); 12624a49301eSmrg} 12634a49301eSmrg 1264af69d88dSmrgstatic void 126501e04c3fSmrgcleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 1266af69d88dSmrg{ 126701e04c3fSmrg _mesa_delete_nameless_texture(ctx, tex->tex_obj); 126801e04c3fSmrg tex->tex_obj = NULL; 1269af69d88dSmrg} 1270af69d88dSmrg 12714a49301eSmrg 12724a49301eSmrg/** 12734a49301eSmrg * Return pointer to temp_texture info for non-bitmap ops. 12744a49301eSmrg * This does some one-time init if needed. 12754a49301eSmrg */ 1276af69d88dSmrgstruct temp_texture * 1277af69d88dSmrg_mesa_meta_get_temp_texture(struct gl_context *ctx) 12784a49301eSmrg{ 12794a49301eSmrg struct temp_texture *tex = &ctx->Meta->TempTex; 12804a49301eSmrg 128101e04c3fSmrg if (tex->tex_obj == NULL) { 12824a49301eSmrg init_temp_texture(ctx, tex); 12834a49301eSmrg } 12844a49301eSmrg 12854a49301eSmrg return tex; 12864a49301eSmrg} 12874a49301eSmrg 12884a49301eSmrg 12894a49301eSmrg/** 12904a49301eSmrg * Return pointer to temp_texture info for _mesa_meta_bitmap(). 12914a49301eSmrg * We use a separate texture for bitmaps to reduce texture 12924a49301eSmrg * allocation/deallocation. 12934a49301eSmrg */ 12944a49301eSmrgstatic struct temp_texture * 12953464ebd5Sriastradhget_bitmap_temp_texture(struct gl_context *ctx) 12964a49301eSmrg{ 12974a49301eSmrg struct temp_texture *tex = &ctx->Meta->Bitmap.Tex; 12984a49301eSmrg 129901e04c3fSmrg if (tex->tex_obj == NULL) { 13004a49301eSmrg init_temp_texture(ctx, tex); 13014a49301eSmrg } 13024a49301eSmrg 13034a49301eSmrg return tex; 13044a49301eSmrg} 13054a49301eSmrg 1306af69d88dSmrg/** 1307af69d88dSmrg * Return pointer to depth temp_texture. 1308af69d88dSmrg * This does some one-time init if needed. 1309af69d88dSmrg */ 1310af69d88dSmrgstruct temp_texture * 1311af69d88dSmrg_mesa_meta_get_temp_depth_texture(struct gl_context *ctx) 1312af69d88dSmrg{ 1313af69d88dSmrg struct temp_texture *tex = &ctx->Meta->Blit.depthTex; 1314af69d88dSmrg 131501e04c3fSmrg if (tex->tex_obj == NULL) { 1316af69d88dSmrg init_temp_texture(ctx, tex); 1317af69d88dSmrg } 1318af69d88dSmrg 1319af69d88dSmrg return tex; 1320af69d88dSmrg} 13214a49301eSmrg 13224a49301eSmrg/** 13234a49301eSmrg * Compute the width/height of texture needed to draw an image of the 13244a49301eSmrg * given size. Return a flag indicating whether the current texture 13254a49301eSmrg * can be re-used (glTexSubImage2D) or if a new texture needs to be 13264a49301eSmrg * allocated (glTexImage2D). 13274a49301eSmrg * Also, compute s/t texcoords for drawing. 13284a49301eSmrg * 13294a49301eSmrg * \return GL_TRUE if new texture is needed, GL_FALSE otherwise 13304a49301eSmrg */ 1331af69d88dSmrgGLboolean 1332af69d88dSmrg_mesa_meta_alloc_texture(struct temp_texture *tex, 1333af69d88dSmrg GLsizei width, GLsizei height, GLenum intFormat) 13344a49301eSmrg{ 13354a49301eSmrg GLboolean newTex = GL_FALSE; 13364a49301eSmrg 133701e04c3fSmrg assert(width <= tex->MaxSize); 133801e04c3fSmrg assert(height <= tex->MaxSize); 13394a49301eSmrg 13404a49301eSmrg if (width > tex->Width || 13414a49301eSmrg height > tex->Height || 13424a49301eSmrg intFormat != tex->IntFormat) { 13434a49301eSmrg /* alloc new texture (larger or different format) */ 13444a49301eSmrg 13454a49301eSmrg if (tex->NPOT) { 13464a49301eSmrg /* use non-power of two size */ 13474a49301eSmrg tex->Width = MAX2(tex->MinSize, width); 13484a49301eSmrg tex->Height = MAX2(tex->MinSize, height); 13494a49301eSmrg } 13504a49301eSmrg else { 13514a49301eSmrg /* find power of two size */ 13524a49301eSmrg GLsizei w, h; 13534a49301eSmrg w = h = tex->MinSize; 13544a49301eSmrg while (w < width) 13554a49301eSmrg w *= 2; 13564a49301eSmrg while (h < height) 13574a49301eSmrg h *= 2; 13584a49301eSmrg tex->Width = w; 13594a49301eSmrg tex->Height = h; 13604a49301eSmrg } 13614a49301eSmrg 13624a49301eSmrg tex->IntFormat = intFormat; 13634a49301eSmrg 13644a49301eSmrg newTex = GL_TRUE; 13654a49301eSmrg } 13664a49301eSmrg 13674a49301eSmrg /* compute texcoords */ 13684a49301eSmrg if (tex->Target == GL_TEXTURE_RECTANGLE) { 13694a49301eSmrg tex->Sright = (GLfloat) width; 13704a49301eSmrg tex->Ttop = (GLfloat) height; 13714a49301eSmrg } 13724a49301eSmrg else { 13734a49301eSmrg tex->Sright = (GLfloat) width / tex->Width; 13744a49301eSmrg tex->Ttop = (GLfloat) height / tex->Height; 13754a49301eSmrg } 13764a49301eSmrg 13774a49301eSmrg return newTex; 13784a49301eSmrg} 13794a49301eSmrg 13804a49301eSmrg 13814a49301eSmrg/** 13824a49301eSmrg * Setup/load texture for glCopyPixels or glBlitFramebuffer. 13834a49301eSmrg */ 1384af69d88dSmrgvoid 1385af69d88dSmrg_mesa_meta_setup_copypix_texture(struct gl_context *ctx, 1386af69d88dSmrg struct temp_texture *tex, 1387af69d88dSmrg GLint srcX, GLint srcY, 1388af69d88dSmrg GLsizei width, GLsizei height, 1389af69d88dSmrg GLenum intFormat, 1390af69d88dSmrg GLenum filter) 13914a49301eSmrg{ 1392af69d88dSmrg bool newTex; 1393af69d88dSmrg 139401e04c3fSmrg _mesa_bind_texture(ctx, tex->Target, tex->tex_obj); 139501e04c3fSmrg _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MIN_FILTER, 139601e04c3fSmrg (GLint *) &filter, false); 139701e04c3fSmrg _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MAG_FILTER, 139801e04c3fSmrg (GLint *) &filter, false); 13994a49301eSmrg _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 14004a49301eSmrg 1401af69d88dSmrg newTex = _mesa_meta_alloc_texture(tex, width, height, intFormat); 1402af69d88dSmrg 14034a49301eSmrg /* copy framebuffer image to texture */ 14044a49301eSmrg if (newTex) { 14054a49301eSmrg /* create new tex image */ 14064a49301eSmrg if (tex->Width == width && tex->Height == height) { 14074a49301eSmrg /* create new tex with framebuffer data */ 14084a49301eSmrg _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat, 14094a49301eSmrg srcX, srcY, width, height, 0); 14104a49301eSmrg } 14114a49301eSmrg else { 14124a49301eSmrg /* create empty texture */ 14134a49301eSmrg _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 14144a49301eSmrg tex->Width, tex->Height, 0, 14154a49301eSmrg intFormat, GL_UNSIGNED_BYTE, NULL); 14164a49301eSmrg /* load image */ 14174a49301eSmrg _mesa_CopyTexSubImage2D(tex->Target, 0, 14184a49301eSmrg 0, 0, srcX, srcY, width, height); 14194a49301eSmrg } 14204a49301eSmrg } 14214a49301eSmrg else { 14224a49301eSmrg /* replace existing tex image */ 14234a49301eSmrg _mesa_CopyTexSubImage2D(tex->Target, 0, 14244a49301eSmrg 0, 0, srcX, srcY, width, height); 14254a49301eSmrg } 14264a49301eSmrg} 14274a49301eSmrg 14284a49301eSmrg 14294a49301eSmrg/** 14304a49301eSmrg * Setup/load texture for glDrawPixels. 14314a49301eSmrg */ 1432af69d88dSmrgvoid 1433af69d88dSmrg_mesa_meta_setup_drawpix_texture(struct gl_context *ctx, 1434af69d88dSmrg struct temp_texture *tex, 1435af69d88dSmrg GLboolean newTex, 1436af69d88dSmrg GLsizei width, GLsizei height, 1437af69d88dSmrg GLenum format, GLenum type, 1438af69d88dSmrg const GLvoid *pixels) 14394a49301eSmrg{ 144001e04c3fSmrg /* GLint so the compiler won't complain about type signedness mismatch in 144101e04c3fSmrg * the call to _mesa_texture_parameteriv below. 144201e04c3fSmrg */ 144301e04c3fSmrg static const GLint filter = GL_NEAREST; 144401e04c3fSmrg 144501e04c3fSmrg _mesa_bind_texture(ctx, tex->Target, tex->tex_obj); 144601e04c3fSmrg _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MIN_FILTER, &filter, 144701e04c3fSmrg false); 144801e04c3fSmrg _mesa_texture_parameteriv(ctx, tex->tex_obj, GL_TEXTURE_MAG_FILTER, &filter, 144901e04c3fSmrg false); 14504a49301eSmrg _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 14514a49301eSmrg 14524a49301eSmrg /* copy pixel data to texture */ 14534a49301eSmrg if (newTex) { 14544a49301eSmrg /* create new tex image */ 14554a49301eSmrg if (tex->Width == width && tex->Height == height) { 14564a49301eSmrg /* create new tex and load image data */ 14574a49301eSmrg _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 14584a49301eSmrg tex->Width, tex->Height, 0, format, type, pixels); 14594a49301eSmrg } 14604a49301eSmrg else { 146101e04c3fSmrg struct gl_buffer_object *save_unpack_obj = NULL; 14624a49301eSmrg 146301e04c3fSmrg _mesa_reference_buffer_object(ctx, &save_unpack_obj, 146401e04c3fSmrg ctx->Unpack.BufferObj); 146501e04c3fSmrg _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 14664a49301eSmrg /* create empty texture */ 14674a49301eSmrg _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 14684a49301eSmrg tex->Width, tex->Height, 0, format, type, NULL); 146901e04c3fSmrg if (save_unpack_obj != NULL) 147001e04c3fSmrg _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 147101e04c3fSmrg save_unpack_obj->Name); 14724a49301eSmrg /* load image */ 14734a49301eSmrg _mesa_TexSubImage2D(tex->Target, 0, 14744a49301eSmrg 0, 0, width, height, format, type, pixels); 1475a8bb7a65Smaya 1476a8bb7a65Smaya _mesa_reference_buffer_object(ctx, &save_unpack_obj, NULL); 14774a49301eSmrg } 14784a49301eSmrg } 14794a49301eSmrg else { 14804a49301eSmrg /* replace existing tex image */ 14814a49301eSmrg _mesa_TexSubImage2D(tex->Target, 0, 14824a49301eSmrg 0, 0, width, height, format, type, pixels); 14834a49301eSmrg } 14844a49301eSmrg} 14854a49301eSmrg 1486af69d88dSmrgvoid 148701e04c3fSmrg_mesa_meta_setup_ff_tnl_for_blit(struct gl_context *ctx, 148801e04c3fSmrg GLuint *VAO, struct gl_buffer_object **buf_obj, 1489af69d88dSmrg unsigned texcoord_size) 1490af69d88dSmrg{ 149101e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, VAO, buf_obj, false, 2, texcoord_size, 149201e04c3fSmrg 0); 14934a49301eSmrg 1494af69d88dSmrg /* setup projection matrix */ 14957ec681f3Smrg _mesa_load_identity_matrix(ctx, &ctx->ProjectionMatrixStack); 1496af69d88dSmrg} 14974a49301eSmrg 14984a49301eSmrg/** 1499af69d88dSmrg * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 15004a49301eSmrg */ 1501af69d88dSmrgvoid 1502af69d88dSmrg_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) 1503af69d88dSmrg{ 1504af69d88dSmrg meta_clear(ctx, buffers, false); 1505af69d88dSmrg} 1506af69d88dSmrg 1507af69d88dSmrgvoid 1508af69d88dSmrg_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) 1509af69d88dSmrg{ 1510af69d88dSmrg meta_clear(ctx, buffers, true); 1511af69d88dSmrg} 1512af69d88dSmrg 15134a49301eSmrgstatic void 1514af69d88dSmrgmeta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) 15154a49301eSmrg{ 1516af69d88dSmrg const char *vs_source = 1517af69d88dSmrg "#extension GL_AMD_vertex_shader_layer : enable\n" 1518af69d88dSmrg "#extension GL_ARB_draw_instanced : enable\n" 151901e04c3fSmrg "#extension GL_ARB_explicit_attrib_location :enable\n" 152001e04c3fSmrg "layout(location = 0) in vec4 position;\n" 1521af69d88dSmrg "void main()\n" 1522af69d88dSmrg "{\n" 1523af69d88dSmrg "#ifdef GL_AMD_vertex_shader_layer\n" 1524af69d88dSmrg " gl_Layer = gl_InstanceID;\n" 1525af69d88dSmrg "#endif\n" 1526af69d88dSmrg " gl_Position = position;\n" 1527af69d88dSmrg "}\n"; 1528af69d88dSmrg const char *fs_source = 152901e04c3fSmrg "#extension GL_ARB_explicit_attrib_location :enable\n" 153001e04c3fSmrg "#extension GL_ARB_explicit_uniform_location :enable\n" 153101e04c3fSmrg "layout(location = 0) uniform vec4 color;\n" 1532af69d88dSmrg "void main()\n" 1533af69d88dSmrg "{\n" 1534af69d88dSmrg " gl_FragColor = color;\n" 1535af69d88dSmrg "}\n"; 1536af69d88dSmrg 153701e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->buf_obj, true, 153801e04c3fSmrg 3, 0, 0); 1539af69d88dSmrg 1540af69d88dSmrg if (clear->ShaderProg != 0) 1541af69d88dSmrg return; 15424a49301eSmrg 154301e04c3fSmrg _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, "meta clear", 154401e04c3fSmrg &clear->ShaderProg); 15454a49301eSmrg} 15464a49301eSmrg 1547af69d88dSmrgstatic void 154801e04c3fSmrgmeta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear) 1549af69d88dSmrg{ 1550af69d88dSmrg if (clear->VAO == 0) 1551af69d88dSmrg return; 1552af69d88dSmrg _mesa_DeleteVertexArrays(1, &clear->VAO); 1553af69d88dSmrg clear->VAO = 0; 155401e04c3fSmrg _mesa_reference_buffer_object(ctx, &clear->buf_obj, NULL); 155501e04c3fSmrg _mesa_reference_shader_program(ctx, &clear->ShaderProg, NULL); 1556af69d88dSmrg} 15574a49301eSmrg 1558a8bb7a65Smayastatic void 1559a8bb7a65Smayameta_copypix_cleanup(struct gl_context *ctx, struct copypix_state *copypix) 1560a8bb7a65Smaya{ 1561a8bb7a65Smaya if (copypix->VAO == 0) 1562a8bb7a65Smaya return; 1563a8bb7a65Smaya _mesa_DeleteVertexArrays(1, ©pix->VAO); 1564a8bb7a65Smaya copypix->VAO = 0; 1565a8bb7a65Smaya _mesa_reference_buffer_object(ctx, ©pix->buf_obj, NULL); 1566a8bb7a65Smaya} 1567a8bb7a65Smaya 1568a8bb7a65Smaya 15694a49301eSmrg/** 1570af69d88dSmrg * Given a bitfield of BUFFER_BIT_x draw buffers, call glDrawBuffers to 1571af69d88dSmrg * set GL to only draw to those buffers. 15724a49301eSmrg * 1573af69d88dSmrg * Since the bitfield has no associated order, the assignment of draw buffer 1574af69d88dSmrg * indices to color attachment indices is rather arbitrary. 15754a49301eSmrg */ 1576af69d88dSmrgvoid 1577af69d88dSmrg_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits) 15784a49301eSmrg{ 1579af69d88dSmrg GLenum enums[MAX_DRAW_BUFFERS]; 1580af69d88dSmrg int i = 0; 1581af69d88dSmrg int n; 15824a49301eSmrg 1583af69d88dSmrg /* This function is only legal for color buffer bitfields. */ 1584af69d88dSmrg assert((bits & ~BUFFER_BITS_COLOR) == 0); 15854a49301eSmrg 1586af69d88dSmrg /* Make sure we don't overflow any arrays. */ 158701e04c3fSmrg assert(util_bitcount(bits) <= MAX_DRAW_BUFFERS); 15883464ebd5Sriastradh 1589af69d88dSmrg enums[0] = GL_NONE; 15903464ebd5Sriastradh 1591af69d88dSmrg if (bits & BUFFER_BIT_FRONT_LEFT) 1592af69d88dSmrg enums[i++] = GL_FRONT_LEFT; 15934a49301eSmrg 1594af69d88dSmrg if (bits & BUFFER_BIT_FRONT_RIGHT) 1595af69d88dSmrg enums[i++] = GL_FRONT_RIGHT; 15964a49301eSmrg 1597af69d88dSmrg if (bits & BUFFER_BIT_BACK_LEFT) 1598af69d88dSmrg enums[i++] = GL_BACK_LEFT; 15994a49301eSmrg 1600af69d88dSmrg if (bits & BUFFER_BIT_BACK_RIGHT) 1601af69d88dSmrg enums[i++] = GL_BACK_RIGHT; 16024a49301eSmrg 1603af69d88dSmrg for (n = 0; n < MAX_COLOR_ATTACHMENTS; n++) { 1604af69d88dSmrg if (bits & (1 << (BUFFER_COLOR0 + n))) 1605af69d88dSmrg enums[i++] = GL_COLOR_ATTACHMENT0 + n; 16064a49301eSmrg } 16074a49301eSmrg 1608af69d88dSmrg _mesa_DrawBuffers(i, enums); 16094a49301eSmrg} 16104a49301eSmrg 161101e04c3fSmrg/** 161201e04c3fSmrg * Given a bitfield of BUFFER_BIT_x draw buffers, call glDrawBuffers to 161301e04c3fSmrg * set GL to only draw to those buffers. Also, update color masks to 161401e04c3fSmrg * reflect the new draw buffer ordering. 161501e04c3fSmrg */ 161601e04c3fSmrgstatic void 161701e04c3fSmrg_mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask) 161801e04c3fSmrg{ 161901e04c3fSmrg GLenum enums[MAX_DRAW_BUFFERS]; 162001e04c3fSmrg GLubyte colormask[MAX_DRAW_BUFFERS][4]; 162101e04c3fSmrg int num_bufs = 0; 162201e04c3fSmrg 162301e04c3fSmrg /* This function is only legal for color buffer bitfields. */ 162401e04c3fSmrg assert((mask & ~BUFFER_BITS_COLOR) == 0); 162501e04c3fSmrg 162601e04c3fSmrg /* Make sure we don't overflow any arrays. */ 162701e04c3fSmrg assert(util_bitcount(mask) <= MAX_DRAW_BUFFERS); 162801e04c3fSmrg 162901e04c3fSmrg enums[0] = GL_NONE; 163001e04c3fSmrg 163101e04c3fSmrg for (int i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 163201e04c3fSmrg gl_buffer_index b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; 163301e04c3fSmrg int colormask_idx = ctx->Extensions.EXT_draw_buffers2 ? i : 0; 163401e04c3fSmrg 163501e04c3fSmrg if (b < 0 || !(mask & (1 << b)) || 163601e04c3fSmrg GET_COLORMASK(ctx->Color.ColorMask, colormask_idx) == 0) 163701e04c3fSmrg continue; 163801e04c3fSmrg 163901e04c3fSmrg switch (b) { 164001e04c3fSmrg case BUFFER_FRONT_LEFT: 164101e04c3fSmrg enums[num_bufs] = GL_FRONT_LEFT; 164201e04c3fSmrg break; 164301e04c3fSmrg case BUFFER_FRONT_RIGHT: 164401e04c3fSmrg enums[num_bufs] = GL_FRONT_RIGHT; 164501e04c3fSmrg break; 164601e04c3fSmrg case BUFFER_BACK_LEFT: 164701e04c3fSmrg enums[num_bufs] = GL_BACK_LEFT; 164801e04c3fSmrg break; 164901e04c3fSmrg case BUFFER_BACK_RIGHT: 165001e04c3fSmrg enums[num_bufs] = GL_BACK_RIGHT; 165101e04c3fSmrg break; 165201e04c3fSmrg default: 165301e04c3fSmrg assert(b >= BUFFER_COLOR0 && b <= BUFFER_COLOR7); 165401e04c3fSmrg enums[num_bufs] = GL_COLOR_ATTACHMENT0 + (b - BUFFER_COLOR0); 165501e04c3fSmrg break; 165601e04c3fSmrg } 165701e04c3fSmrg 165801e04c3fSmrg for (int k = 0; k < 4; k++) 165901e04c3fSmrg colormask[num_bufs][k] = GET_COLORMASK_BIT(ctx->Color.ColorMask, 166001e04c3fSmrg colormask_idx, k); 166101e04c3fSmrg 166201e04c3fSmrg num_bufs++; 166301e04c3fSmrg } 166401e04c3fSmrg 166501e04c3fSmrg _mesa_DrawBuffers(num_bufs, enums); 166601e04c3fSmrg 166701e04c3fSmrg for (int i = 0; i < num_bufs; i++) { 166801e04c3fSmrg _mesa_ColorMaski(i, colormask[i][0], colormask[i][1], 166901e04c3fSmrg colormask[i][2], colormask[i][3]); 167001e04c3fSmrg } 167101e04c3fSmrg} 167201e04c3fSmrg 167301e04c3fSmrg 16744a49301eSmrg/** 1675af69d88dSmrg * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 16764a49301eSmrg */ 1677af69d88dSmrgstatic void 1678af69d88dSmrgmeta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl) 16794a49301eSmrg{ 1680af69d88dSmrg struct clear_state *clear = &ctx->Meta->Clear; 1681af69d88dSmrg GLbitfield metaSave; 1682af69d88dSmrg const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 1683af69d88dSmrg struct gl_framebuffer *fb = ctx->DrawBuffer; 16844a49301eSmrg struct vertex verts[4]; 1685af69d88dSmrg 1686af69d88dSmrg metaSave = (MESA_META_ALPHA_TEST | 168701e04c3fSmrg MESA_META_BLEND | 168801e04c3fSmrg MESA_META_COLOR_MASK | 168901e04c3fSmrg MESA_META_DEPTH_TEST | 169001e04c3fSmrg MESA_META_RASTERIZATION | 169101e04c3fSmrg MESA_META_SHADER | 169201e04c3fSmrg MESA_META_STENCIL_TEST | 169301e04c3fSmrg MESA_META_VERTEX | 169401e04c3fSmrg MESA_META_VIEWPORT | 169501e04c3fSmrg MESA_META_CLIP | 169601e04c3fSmrg MESA_META_CLAMP_FRAGMENT_COLOR | 1697af69d88dSmrg MESA_META_MULTISAMPLE | 1698af69d88dSmrg MESA_META_OCCLUSION_QUERY); 1699af69d88dSmrg 1700af69d88dSmrg if (!glsl) { 1701af69d88dSmrg metaSave |= MESA_META_FOG | 1702af69d88dSmrg MESA_META_PIXEL_TRANSFER | 1703af69d88dSmrg MESA_META_TRANSFORM | 1704af69d88dSmrg MESA_META_TEXTURE | 1705af69d88dSmrg MESA_META_CLAMP_VERTEX_COLOR | 1706af69d88dSmrg MESA_META_SELECT_FEEDBACK; 17074a49301eSmrg } 17084a49301eSmrg 17094a49301eSmrg if (buffers & BUFFER_BITS_COLOR) { 1710af69d88dSmrg metaSave |= MESA_META_DRAW_BUFFERS; 17114a49301eSmrg } 17124a49301eSmrg 17134a49301eSmrg _mesa_meta_begin(ctx, metaSave); 17144a49301eSmrg 17157ec681f3Smrg assert(!fb->_IntegerBuffers); 1716af69d88dSmrg if (glsl) { 1717af69d88dSmrg meta_glsl_clear_init(ctx, clear); 17184a49301eSmrg 17197ec681f3Smrg _mesa_meta_use_program(ctx, clear->ShaderProg); 17207ec681f3Smrg _mesa_Uniform4fv(0, 1, ctx->Color.ClearColor.f); 1721af69d88dSmrg } else { 172201e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, &clear->VAO, &clear->buf_obj, false, 172301e04c3fSmrg 3, 0, 4); 17244a49301eSmrg 17257ec681f3Smrg /* setup projection matrix */ 17267ec681f3Smrg _mesa_load_identity_matrix(ctx, &ctx->ProjectionMatrixStack); 1727af69d88dSmrg 17287ec681f3Smrg for (int i = 0; i < 4; i++) { 17297ec681f3Smrg verts[i].r = ctx->Color.ClearColor.f[0]; 17307ec681f3Smrg verts[i].g = ctx->Color.ClearColor.f[1]; 17317ec681f3Smrg verts[i].b = ctx->Color.ClearColor.f[2]; 17327ec681f3Smrg verts[i].a = ctx->Color.ClearColor.f[3]; 17337ec681f3Smrg } 17344a49301eSmrg } 17354a49301eSmrg 17364a49301eSmrg /* GL_COLOR_BUFFER_BIT */ 17374a49301eSmrg if (buffers & BUFFER_BITS_COLOR) { 1738af69d88dSmrg /* Only draw to the buffers we were asked to clear. */ 173901e04c3fSmrg _mesa_meta_drawbuffers_and_colormask(ctx, buffers & BUFFER_BITS_COLOR); 1740af69d88dSmrg 1741af69d88dSmrg /* leave colormask state as-is */ 17423464ebd5Sriastradh 17433464ebd5Sriastradh /* Clears never have the color clamped. */ 1744af69d88dSmrg if (ctx->Extensions.ARB_color_buffer_float) 1745af69d88dSmrg _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 17464a49301eSmrg } 17474a49301eSmrg else { 17484a49301eSmrg _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 17494a49301eSmrg } 17504a49301eSmrg 17514a49301eSmrg /* GL_DEPTH_BUFFER_BIT */ 17524a49301eSmrg if (buffers & BUFFER_BIT_DEPTH) { 17534a49301eSmrg _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 17544a49301eSmrg _mesa_DepthFunc(GL_ALWAYS); 17554a49301eSmrg _mesa_DepthMask(GL_TRUE); 17564a49301eSmrg } 17574a49301eSmrg else { 17584a49301eSmrg assert(!ctx->Depth.Test); 17594a49301eSmrg } 17604a49301eSmrg 17614a49301eSmrg /* GL_STENCIL_BUFFER_BIT */ 17624a49301eSmrg if (buffers & BUFFER_BIT_STENCIL) { 17634a49301eSmrg _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 17644a49301eSmrg _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, 17654a49301eSmrg GL_REPLACE, GL_REPLACE, GL_REPLACE); 17664a49301eSmrg _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 17673464ebd5Sriastradh ctx->Stencil.Clear & stencilMax, 17684a49301eSmrg ctx->Stencil.WriteMask[0]); 17694a49301eSmrg } 17704a49301eSmrg else { 17714a49301eSmrg assert(!ctx->Stencil.Enabled); 17724a49301eSmrg } 17734a49301eSmrg 1774af69d88dSmrg /* vertex positions */ 17757ec681f3Smrg const float x0 = ((float) fb->_Xmin / fb->Width) * 2.0f - 1.0f; 17767ec681f3Smrg const float y0 = ((float) fb->_Ymin / fb->Height) * 2.0f - 1.0f; 17777ec681f3Smrg const float x1 = ((float) fb->_Xmax / fb->Width) * 2.0f - 1.0f; 17787ec681f3Smrg const float y1 = ((float) fb->_Ymax / fb->Height) * 2.0f - 1.0f; 17797ec681f3Smrg const float z = -invert_z(ctx->Depth.Clear); 17807ec681f3Smrg 1781af69d88dSmrg verts[0].x = x0; 1782af69d88dSmrg verts[0].y = y0; 1783af69d88dSmrg verts[0].z = z; 1784af69d88dSmrg verts[1].x = x1; 1785af69d88dSmrg verts[1].y = y0; 1786af69d88dSmrg verts[1].z = z; 1787af69d88dSmrg verts[2].x = x1; 1788af69d88dSmrg verts[2].y = y1; 1789af69d88dSmrg verts[2].z = z; 1790af69d88dSmrg verts[3].x = x0; 1791af69d88dSmrg verts[3].y = y1; 1792af69d88dSmrg verts[3].z = z; 1793af69d88dSmrg 1794af69d88dSmrg /* upload new vertex data */ 179501e04c3fSmrg _mesa_buffer_data(ctx, clear->buf_obj, GL_NONE, sizeof(verts), verts, 179601e04c3fSmrg GL_DYNAMIC_DRAW, __func__); 1797af69d88dSmrg 1798af69d88dSmrg /* draw quad(s) */ 1799af69d88dSmrg if (fb->MaxNumLayers > 0) { 18007ec681f3Smrg _mesa_DrawArraysInstancedARB(GL_TRIANGLE_FAN, 0, 4, fb->MaxNumLayers); 1801af69d88dSmrg } else { 1802af69d88dSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1803af69d88dSmrg } 18044a49301eSmrg 18054a49301eSmrg _mesa_meta_end(ctx); 18064a49301eSmrg} 18074a49301eSmrg 18084a49301eSmrg/** 18094a49301eSmrg * Meta implementation of ctx->Driver.CopyPixels() in terms 1810af69d88dSmrg * of texture mapping and polygon rendering and GLSL shaders. 18114a49301eSmrg */ 18124a49301eSmrgvoid 18133464ebd5Sriastradh_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, 18144a49301eSmrg GLsizei width, GLsizei height, 18154a49301eSmrg GLint dstX, GLint dstY, GLenum type) 18164a49301eSmrg{ 18174a49301eSmrg struct copypix_state *copypix = &ctx->Meta->CopyPix; 1818af69d88dSmrg struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); 18194a49301eSmrg struct vertex verts[4]; 18204a49301eSmrg 18214a49301eSmrg if (type != GL_COLOR || 18224a49301eSmrg ctx->_ImageTransferState || 18234a49301eSmrg ctx->Fog.Enabled || 18244a49301eSmrg width > tex->MaxSize || 18254a49301eSmrg height > tex->MaxSize) { 18264a49301eSmrg /* XXX avoid this fallback */ 18274a49301eSmrg _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type); 18284a49301eSmrg return; 18294a49301eSmrg } 18304a49301eSmrg 18314a49301eSmrg /* Most GL state applies to glCopyPixels, but a there's a few things 18324a49301eSmrg * we need to override: 18334a49301eSmrg */ 1834af69d88dSmrg _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 1835af69d88dSmrg MESA_META_SHADER | 1836af69d88dSmrg MESA_META_TEXTURE | 1837af69d88dSmrg MESA_META_TRANSFORM | 1838af69d88dSmrg MESA_META_CLIP | 1839af69d88dSmrg MESA_META_VERTEX | 1840af69d88dSmrg MESA_META_VIEWPORT)); 18414a49301eSmrg 184201e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, ©pix->VAO, ©pix->buf_obj, false, 1843af69d88dSmrg 3, 2, 0); 18444a49301eSmrg 1845af69d88dSmrg /* Silence valgrind warnings about reading uninitialized stack. */ 1846af69d88dSmrg memset(verts, 0, sizeof(verts)); 18474a49301eSmrg 1848af69d88dSmrg /* Alloc/setup texture */ 1849af69d88dSmrg _mesa_meta_setup_copypix_texture(ctx, tex, srcX, srcY, width, height, 1850af69d88dSmrg GL_RGBA, GL_NEAREST); 18514a49301eSmrg 18524a49301eSmrg /* vertex positions, texcoords (after texture allocation!) */ 18534a49301eSmrg { 18544a49301eSmrg const GLfloat dstX0 = (GLfloat) dstX; 18554a49301eSmrg const GLfloat dstY0 = (GLfloat) dstY; 18564a49301eSmrg const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX; 18574a49301eSmrg const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY; 1858cdc920a0Smrg const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 18594a49301eSmrg 18604a49301eSmrg verts[0].x = dstX0; 18614a49301eSmrg verts[0].y = dstY0; 18624a49301eSmrg verts[0].z = z; 1863af69d88dSmrg verts[0].tex[0] = 0.0F; 1864af69d88dSmrg verts[0].tex[1] = 0.0F; 18654a49301eSmrg verts[1].x = dstX1; 18664a49301eSmrg verts[1].y = dstY0; 18674a49301eSmrg verts[1].z = z; 1868af69d88dSmrg verts[1].tex[0] = tex->Sright; 1869af69d88dSmrg verts[1].tex[1] = 0.0F; 18704a49301eSmrg verts[2].x = dstX1; 18714a49301eSmrg verts[2].y = dstY1; 18724a49301eSmrg verts[2].z = z; 1873af69d88dSmrg verts[2].tex[0] = tex->Sright; 1874af69d88dSmrg verts[2].tex[1] = tex->Ttop; 18754a49301eSmrg verts[3].x = dstX0; 18764a49301eSmrg verts[3].y = dstY1; 18774a49301eSmrg verts[3].z = z; 1878af69d88dSmrg verts[3].tex[0] = 0.0F; 1879af69d88dSmrg verts[3].tex[1] = tex->Ttop; 18804a49301eSmrg 18814a49301eSmrg /* upload new vertex data */ 188201e04c3fSmrg _mesa_buffer_sub_data(ctx, copypix->buf_obj, 0, sizeof(verts), verts); 18834a49301eSmrg } 18844a49301eSmrg 18854a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_TRUE); 18864a49301eSmrg 18874a49301eSmrg /* draw textured quad */ 18884a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 18894a49301eSmrg 18904a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_FALSE); 18914a49301eSmrg 18924a49301eSmrg _mesa_meta_end(ctx); 18934a49301eSmrg} 18944a49301eSmrg 1895af69d88dSmrgstatic void 189601e04c3fSmrgmeta_drawpix_cleanup(struct gl_context *ctx, struct drawpix_state *drawpix) 1897af69d88dSmrg{ 1898af69d88dSmrg if (drawpix->VAO != 0) { 1899af69d88dSmrg _mesa_DeleteVertexArrays(1, &drawpix->VAO); 1900af69d88dSmrg drawpix->VAO = 0; 1901af69d88dSmrg 190201e04c3fSmrg _mesa_reference_buffer_object(ctx, &drawpix->buf_obj, NULL); 1903af69d88dSmrg } 1904af69d88dSmrg 1905af69d88dSmrg if (drawpix->StencilFP != 0) { 1906af69d88dSmrg _mesa_DeleteProgramsARB(1, &drawpix->StencilFP); 1907af69d88dSmrg drawpix->StencilFP = 0; 1908af69d88dSmrg } 19094a49301eSmrg 1910af69d88dSmrg if (drawpix->DepthFP != 0) { 1911af69d88dSmrg _mesa_DeleteProgramsARB(1, &drawpix->DepthFP); 1912af69d88dSmrg drawpix->DepthFP = 0; 1913af69d88dSmrg } 1914af69d88dSmrg} 19154a49301eSmrg 19167ec681f3Smrgstatic void 19177ec681f3Smrgmeta_drawtex_cleanup(struct gl_context *ctx, struct drawtex_state *drawtex) 19187ec681f3Smrg{ 19197ec681f3Smrg if (drawtex->VAO != 0) { 19207ec681f3Smrg _mesa_DeleteVertexArrays(1, &drawtex->VAO); 19217ec681f3Smrg drawtex->VAO = 0; 19227ec681f3Smrg 19237ec681f3Smrg _mesa_reference_buffer_object(ctx, &drawtex->buf_obj, NULL); 19247ec681f3Smrg } 19257ec681f3Smrg} 19267ec681f3Smrg 19277ec681f3Smrgstatic void 19287ec681f3Smrgmeta_bitmap_cleanup(struct gl_context *ctx, struct bitmap_state *bitmap) 19297ec681f3Smrg{ 19307ec681f3Smrg if (bitmap->VAO != 0) { 19317ec681f3Smrg _mesa_DeleteVertexArrays(1, &bitmap->VAO); 19327ec681f3Smrg bitmap->VAO = 0; 19337ec681f3Smrg 19347ec681f3Smrg _mesa_reference_buffer_object(ctx, &bitmap->buf_obj, NULL); 19357ec681f3Smrg 19367ec681f3Smrg cleanup_temp_texture(ctx, &bitmap->Tex); 19377ec681f3Smrg } 19387ec681f3Smrg} 19397ec681f3Smrg 19404a49301eSmrg/** 19414a49301eSmrg * When the glDrawPixels() image size is greater than the max rectangle 19424a49301eSmrg * texture size we use this function to break the glDrawPixels() image 19434a49301eSmrg * into tiles which fit into the max texture size. 19444a49301eSmrg */ 19454a49301eSmrgstatic void 19463464ebd5Sriastradhtiled_draw_pixels(struct gl_context *ctx, 19474a49301eSmrg GLint tileSize, 19484a49301eSmrg GLint x, GLint y, GLsizei width, GLsizei height, 19494a49301eSmrg GLenum format, GLenum type, 19504a49301eSmrg const struct gl_pixelstore_attrib *unpack, 19514a49301eSmrg const GLvoid *pixels) 19524a49301eSmrg{ 19534a49301eSmrg struct gl_pixelstore_attrib tileUnpack = *unpack; 19544a49301eSmrg GLint i, j; 19554a49301eSmrg 19564a49301eSmrg if (tileUnpack.RowLength == 0) 19574a49301eSmrg tileUnpack.RowLength = width; 19584a49301eSmrg 19594a49301eSmrg for (i = 0; i < width; i += tileSize) { 19604a49301eSmrg const GLint tileWidth = MIN2(tileSize, width - i); 19614a49301eSmrg const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX); 19624a49301eSmrg 19634a49301eSmrg tileUnpack.SkipPixels = unpack->SkipPixels + i; 19644a49301eSmrg 19654a49301eSmrg for (j = 0; j < height; j += tileSize) { 19664a49301eSmrg const GLint tileHeight = MIN2(tileSize, height - j); 19674a49301eSmrg const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY); 19684a49301eSmrg 19694a49301eSmrg tileUnpack.SkipRows = unpack->SkipRows + j; 19704a49301eSmrg 19714a49301eSmrg _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight, 19724a49301eSmrg format, type, &tileUnpack, pixels); 19734a49301eSmrg } 19744a49301eSmrg } 19754a49301eSmrg} 19764a49301eSmrg 19774a49301eSmrg 19784a49301eSmrg/** 19794a49301eSmrg * One-time init for drawing stencil pixels. 19804a49301eSmrg */ 19814a49301eSmrgstatic void 19823464ebd5Sriastradhinit_draw_stencil_pixels(struct gl_context *ctx) 19834a49301eSmrg{ 19844a49301eSmrg /* This program is run eight times, once for each stencil bit. 19854a49301eSmrg * The stencil values to draw are found in an 8-bit alpha texture. 19864a49301eSmrg * We read the texture/stencil value and test if bit 'b' is set. 19874a49301eSmrg * If the bit is not set, use KIL to kill the fragment. 19884a49301eSmrg * Finally, we use the stencil test to update the stencil buffer. 19894a49301eSmrg * 19904a49301eSmrg * The basic algorithm for checking if a bit is set is: 19914a49301eSmrg * if (is_odd(value / (1 << bit))) 19924a49301eSmrg * result is one (or non-zero). 19934a49301eSmrg * else 19944a49301eSmrg * result is zero. 19954a49301eSmrg * The program parameter contains three values: 19964a49301eSmrg * parm.x = 255 / (1 << bit) 19974a49301eSmrg * parm.y = 0.5 19984a49301eSmrg * parm.z = 0.0 19994a49301eSmrg */ 20004a49301eSmrg static const char *program = 20014a49301eSmrg "!!ARBfp1.0\n" 20024a49301eSmrg "PARAM parm = program.local[0]; \n" 20034a49301eSmrg "TEMP t; \n" 20044a49301eSmrg "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */ 20054a49301eSmrg "# t = t * 255 / bit \n" 20064a49301eSmrg "MUL t.x, t.a, parm.x; \n" 20074a49301eSmrg "# t = (int) t \n" 20084a49301eSmrg "FRC t.y, t.x; \n" 20094a49301eSmrg "SUB t.x, t.x, t.y; \n" 20104a49301eSmrg "# t = t * 0.5 \n" 20114a49301eSmrg "MUL t.x, t.x, parm.y; \n" 20124a49301eSmrg "# t = fract(t.x) \n" 20134a49301eSmrg "FRC t.x, t.x; # if t.x != 0, then the bit is set \n" 20144a49301eSmrg "# t.x = (t.x == 0 ? 1 : 0) \n" 20154a49301eSmrg "SGE t.x, -t.x, parm.z; \n" 20164a49301eSmrg "KIL -t.x; \n" 20174a49301eSmrg "# for debug only \n" 20184a49301eSmrg "#MOV result.color, t.x; \n" 20194a49301eSmrg "END \n"; 20204a49301eSmrg char program2[1000]; 20214a49301eSmrg struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2022af69d88dSmrg struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); 20234a49301eSmrg const char *texTarget; 20244a49301eSmrg 20254a49301eSmrg assert(drawpix->StencilFP == 0); 20264a49301eSmrg 20274a49301eSmrg /* replace %s with "RECT" or "2D" */ 20284a49301eSmrg assert(strlen(program) + 4 < sizeof(program2)); 20294a49301eSmrg if (tex->Target == GL_TEXTURE_RECTANGLE) 20304a49301eSmrg texTarget = "RECT"; 20314a49301eSmrg else 20324a49301eSmrg texTarget = "2D"; 20337ec681f3Smrg snprintf(program2, sizeof(program2), program, texTarget); 20344a49301eSmrg 2035af69d88dSmrg _mesa_GenProgramsARB(1, &drawpix->StencilFP); 2036af69d88dSmrg _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 20374a49301eSmrg _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 20384a49301eSmrg strlen(program2), (const GLubyte *) program2); 20394a49301eSmrg} 20404a49301eSmrg 20414a49301eSmrg 20424a49301eSmrg/** 20434a49301eSmrg * One-time init for drawing depth pixels. 20444a49301eSmrg */ 20454a49301eSmrgstatic void 20463464ebd5Sriastradhinit_draw_depth_pixels(struct gl_context *ctx) 20474a49301eSmrg{ 20484a49301eSmrg static const char *program = 20494a49301eSmrg "!!ARBfp1.0\n" 20504a49301eSmrg "PARAM color = program.local[0]; \n" 20514a49301eSmrg "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" 20524a49301eSmrg "MOV result.color, color; \n" 20534a49301eSmrg "END \n"; 20544a49301eSmrg char program2[200]; 20554a49301eSmrg struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2056af69d88dSmrg struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); 20574a49301eSmrg const char *texTarget; 20584a49301eSmrg 20594a49301eSmrg assert(drawpix->DepthFP == 0); 20604a49301eSmrg 20614a49301eSmrg /* replace %s with "RECT" or "2D" */ 20624a49301eSmrg assert(strlen(program) + 4 < sizeof(program2)); 20634a49301eSmrg if (tex->Target == GL_TEXTURE_RECTANGLE) 20644a49301eSmrg texTarget = "RECT"; 20654a49301eSmrg else 20664a49301eSmrg texTarget = "2D"; 20677ec681f3Smrg snprintf(program2, sizeof(program2), program, texTarget); 20684a49301eSmrg 2069af69d88dSmrg _mesa_GenProgramsARB(1, &drawpix->DepthFP); 2070af69d88dSmrg _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 20714a49301eSmrg _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 20724a49301eSmrg strlen(program2), (const GLubyte *) program2); 20734a49301eSmrg} 20744a49301eSmrg 20754a49301eSmrg 20764a49301eSmrg/** 20774a49301eSmrg * Meta implementation of ctx->Driver.DrawPixels() in terms 20784a49301eSmrg * of texture mapping and polygon rendering. 20794a49301eSmrg */ 20804a49301eSmrgvoid 20813464ebd5Sriastradh_mesa_meta_DrawPixels(struct gl_context *ctx, 20824a49301eSmrg GLint x, GLint y, GLsizei width, GLsizei height, 20834a49301eSmrg GLenum format, GLenum type, 20844a49301eSmrg const struct gl_pixelstore_attrib *unpack, 20854a49301eSmrg const GLvoid *pixels) 20864a49301eSmrg{ 20874a49301eSmrg struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2088af69d88dSmrg struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); 20894a49301eSmrg const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; 20904a49301eSmrg const GLuint origStencilMask = ctx->Stencil.WriteMask[0]; 20914a49301eSmrg struct vertex verts[4]; 20924a49301eSmrg GLenum texIntFormat; 20934a49301eSmrg GLboolean fallback, newTex; 20944a49301eSmrg GLbitfield metaExtraSave = 0x0; 20954a49301eSmrg 20964a49301eSmrg /* 20974a49301eSmrg * Determine if we can do the glDrawPixels with texture mapping. 20984a49301eSmrg */ 20994a49301eSmrg fallback = GL_FALSE; 2100af69d88dSmrg if (ctx->Fog.Enabled) { 21014a49301eSmrg fallback = GL_TRUE; 21024a49301eSmrg } 21034a49301eSmrg 21044a49301eSmrg if (_mesa_is_color_format(format)) { 21054a49301eSmrg /* use more compact format when possible */ 21064a49301eSmrg /* XXX disable special case for GL_LUMINANCE for now to work around 21074a49301eSmrg * apparent i965 driver bug (see bug #23670). 21084a49301eSmrg */ 21094a49301eSmrg if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA) 21104a49301eSmrg texIntFormat = format; 21114a49301eSmrg else 21124a49301eSmrg texIntFormat = GL_RGBA; 21133464ebd5Sriastradh 21143464ebd5Sriastradh /* If we're not supposed to clamp the resulting color, then just 21153464ebd5Sriastradh * promote our texture to fully float. We could do better by 21163464ebd5Sriastradh * just going for the matching set of channels, in floating 21173464ebd5Sriastradh * point. 21183464ebd5Sriastradh */ 21193464ebd5Sriastradh if (ctx->Color.ClampFragmentColor != GL_TRUE && 212001e04c3fSmrg ctx->Extensions.ARB_texture_float) 212101e04c3fSmrg texIntFormat = GL_RGBA32F; 21224a49301eSmrg } 21234a49301eSmrg else if (_mesa_is_stencil_format(format)) { 21244a49301eSmrg if (ctx->Extensions.ARB_fragment_program && 21254a49301eSmrg ctx->Pixel.IndexShift == 0 && 21264a49301eSmrg ctx->Pixel.IndexOffset == 0 && 21274a49301eSmrg type == GL_UNSIGNED_BYTE) { 21284a49301eSmrg /* We'll store stencil as alpha. This only works for GLubyte 21294a49301eSmrg * image data because of how incoming values are mapped to alpha 21304a49301eSmrg * in [0,1]. 21314a49301eSmrg */ 21324a49301eSmrg texIntFormat = GL_ALPHA; 2133af69d88dSmrg metaExtraSave = (MESA_META_COLOR_MASK | 2134af69d88dSmrg MESA_META_DEPTH_TEST | 2135af69d88dSmrg MESA_META_PIXEL_TRANSFER | 2136af69d88dSmrg MESA_META_SHADER | 2137af69d88dSmrg MESA_META_STENCIL_TEST); 21384a49301eSmrg } 21394a49301eSmrg else { 21404a49301eSmrg fallback = GL_TRUE; 21414a49301eSmrg } 21424a49301eSmrg } 21434a49301eSmrg else if (_mesa_is_depth_format(format)) { 21444a49301eSmrg if (ctx->Extensions.ARB_depth_texture && 21454a49301eSmrg ctx->Extensions.ARB_fragment_program) { 21464a49301eSmrg texIntFormat = GL_DEPTH_COMPONENT; 2147af69d88dSmrg metaExtraSave = (MESA_META_SHADER); 21484a49301eSmrg } 21494a49301eSmrg else { 21504a49301eSmrg fallback = GL_TRUE; 21514a49301eSmrg } 21524a49301eSmrg } 21534a49301eSmrg else { 21544a49301eSmrg fallback = GL_TRUE; 21554a49301eSmrg } 21564a49301eSmrg 21574a49301eSmrg if (fallback) { 21584a49301eSmrg _swrast_DrawPixels(ctx, x, y, width, height, 21594a49301eSmrg format, type, unpack, pixels); 21604a49301eSmrg return; 21614a49301eSmrg } 21624a49301eSmrg 21634a49301eSmrg /* 21644a49301eSmrg * Check image size against max texture size, draw as tiles if needed. 21654a49301eSmrg */ 21664a49301eSmrg if (width > tex->MaxSize || height > tex->MaxSize) { 21674a49301eSmrg tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height, 21684a49301eSmrg format, type, unpack, pixels); 21694a49301eSmrg return; 21704a49301eSmrg } 21714a49301eSmrg 21724a49301eSmrg /* Most GL state applies to glDrawPixels (like blending, stencil, etc), 21734a49301eSmrg * but a there's a few things we need to override: 21744a49301eSmrg */ 2175af69d88dSmrg _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 2176af69d88dSmrg MESA_META_SHADER | 2177af69d88dSmrg MESA_META_TEXTURE | 2178af69d88dSmrg MESA_META_TRANSFORM | 2179af69d88dSmrg MESA_META_CLIP | 2180af69d88dSmrg MESA_META_VERTEX | 2181af69d88dSmrg MESA_META_VIEWPORT | 21824a49301eSmrg metaExtraSave)); 21834a49301eSmrg 2184af69d88dSmrg newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); 2185af69d88dSmrg 218601e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, &drawpix->VAO, &drawpix->buf_obj, false, 2187af69d88dSmrg 3, 2, 0); 2188af69d88dSmrg 2189af69d88dSmrg /* Silence valgrind warnings about reading uninitialized stack. */ 2190af69d88dSmrg memset(verts, 0, sizeof(verts)); 21914a49301eSmrg 21924a49301eSmrg /* vertex positions, texcoords (after texture allocation!) */ 21934a49301eSmrg { 21944a49301eSmrg const GLfloat x0 = (GLfloat) x; 21954a49301eSmrg const GLfloat y0 = (GLfloat) y; 21964a49301eSmrg const GLfloat x1 = x + width * ctx->Pixel.ZoomX; 21974a49301eSmrg const GLfloat y1 = y + height * ctx->Pixel.ZoomY; 2198cdc920a0Smrg const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 21994a49301eSmrg 22004a49301eSmrg verts[0].x = x0; 22014a49301eSmrg verts[0].y = y0; 22024a49301eSmrg verts[0].z = z; 2203af69d88dSmrg verts[0].tex[0] = 0.0F; 2204af69d88dSmrg verts[0].tex[1] = 0.0F; 22054a49301eSmrg verts[1].x = x1; 22064a49301eSmrg verts[1].y = y0; 22074a49301eSmrg verts[1].z = z; 2208af69d88dSmrg verts[1].tex[0] = tex->Sright; 2209af69d88dSmrg verts[1].tex[1] = 0.0F; 22104a49301eSmrg verts[2].x = x1; 22114a49301eSmrg verts[2].y = y1; 22124a49301eSmrg verts[2].z = z; 2213af69d88dSmrg verts[2].tex[0] = tex->Sright; 2214af69d88dSmrg verts[2].tex[1] = tex->Ttop; 22154a49301eSmrg verts[3].x = x0; 22164a49301eSmrg verts[3].y = y1; 22174a49301eSmrg verts[3].z = z; 2218af69d88dSmrg verts[3].tex[0] = 0.0F; 2219af69d88dSmrg verts[3].tex[1] = tex->Ttop; 22204a49301eSmrg } 22214a49301eSmrg 2222af69d88dSmrg /* upload new vertex data */ 222301e04c3fSmrg _mesa_buffer_data(ctx, drawpix->buf_obj, GL_NONE, sizeof(verts), verts, 222401e04c3fSmrg GL_DYNAMIC_DRAW, __func__); 22254a49301eSmrg 22264a49301eSmrg /* set given unpack params */ 22274a49301eSmrg ctx->Unpack = *unpack; 22284a49301eSmrg 22294a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_TRUE); 22304a49301eSmrg 22314a49301eSmrg if (_mesa_is_stencil_format(format)) { 22324a49301eSmrg /* Drawing stencil */ 22334a49301eSmrg GLint bit; 22344a49301eSmrg 22354a49301eSmrg if (!drawpix->StencilFP) 22364a49301eSmrg init_draw_stencil_pixels(ctx); 22374a49301eSmrg 2238af69d88dSmrg _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, 2239af69d88dSmrg GL_ALPHA, type, pixels); 22404a49301eSmrg 22414a49301eSmrg _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 22424a49301eSmrg 22434a49301eSmrg _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 22444a49301eSmrg 22454a49301eSmrg /* set all stencil bits to 0 */ 22464a49301eSmrg _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 22474a49301eSmrg _mesa_StencilFunc(GL_ALWAYS, 0, 255); 22484a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 22497ec681f3Smrg 22504a49301eSmrg /* set stencil bits to 1 where needed */ 22514a49301eSmrg _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 22524a49301eSmrg 2253af69d88dSmrg _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 22544a49301eSmrg _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 22554a49301eSmrg 2256cdc920a0Smrg for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) { 22574a49301eSmrg const GLuint mask = 1 << bit; 22584a49301eSmrg if (mask & origStencilMask) { 22594a49301eSmrg _mesa_StencilFunc(GL_ALWAYS, mask, mask); 22604a49301eSmrg _mesa_StencilMask(mask); 22614a49301eSmrg 22624a49301eSmrg _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 2263af69d88dSmrg 255.0f / mask, 0.5f, 0.0f, 0.0f); 22644a49301eSmrg 22654a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 22664a49301eSmrg } 22674a49301eSmrg } 22684a49301eSmrg } 22694a49301eSmrg else if (_mesa_is_depth_format(format)) { 22704a49301eSmrg /* Drawing depth */ 22714a49301eSmrg if (!drawpix->DepthFP) 22724a49301eSmrg init_draw_depth_pixels(ctx); 22734a49301eSmrg 2274af69d88dSmrg _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 22754a49301eSmrg _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 22764a49301eSmrg 22774a49301eSmrg /* polygon color = current raster color */ 22784a49301eSmrg _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, 22794a49301eSmrg ctx->Current.RasterColor); 22804a49301eSmrg 2281af69d88dSmrg _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, 2282af69d88dSmrg format, type, pixels); 22834a49301eSmrg 22844a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 22854a49301eSmrg } 22864a49301eSmrg else { 22874a49301eSmrg /* Drawing RGBA */ 2288af69d88dSmrg _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, 2289af69d88dSmrg format, type, pixels); 22904a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 22914a49301eSmrg } 22924a49301eSmrg 22934a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_FALSE); 22944a49301eSmrg 22954a49301eSmrg /* restore unpack params */ 22964a49301eSmrg ctx->Unpack = unpackSave; 22974a49301eSmrg 22984a49301eSmrg _mesa_meta_end(ctx); 22994a49301eSmrg} 23004a49301eSmrg 23013464ebd5Sriastradhstatic GLboolean 23023464ebd5Sriastradhalpha_test_raster_color(struct gl_context *ctx) 23033464ebd5Sriastradh{ 23043464ebd5Sriastradh GLfloat alpha = ctx->Current.RasterColor[ACOMP]; 23053464ebd5Sriastradh GLfloat ref = ctx->Color.AlphaRef; 23063464ebd5Sriastradh 23073464ebd5Sriastradh switch (ctx->Color.AlphaFunc) { 23083464ebd5Sriastradh case GL_NEVER: 230901e04c3fSmrg return GL_FALSE; 23103464ebd5Sriastradh case GL_LESS: 231101e04c3fSmrg return alpha < ref; 23123464ebd5Sriastradh case GL_EQUAL: 231301e04c3fSmrg return alpha == ref; 23143464ebd5Sriastradh case GL_LEQUAL: 231501e04c3fSmrg return alpha <= ref; 23163464ebd5Sriastradh case GL_GREATER: 231701e04c3fSmrg return alpha > ref; 23183464ebd5Sriastradh case GL_NOTEQUAL: 231901e04c3fSmrg return alpha != ref; 23203464ebd5Sriastradh case GL_GEQUAL: 232101e04c3fSmrg return alpha >= ref; 23223464ebd5Sriastradh case GL_ALWAYS: 232301e04c3fSmrg return GL_TRUE; 23243464ebd5Sriastradh default: 232501e04c3fSmrg assert(0); 232601e04c3fSmrg return GL_FALSE; 23273464ebd5Sriastradh } 23283464ebd5Sriastradh} 23294a49301eSmrg 23304a49301eSmrg/** 23313464ebd5Sriastradh * Do glBitmap with a alpha texture quad. Use the alpha test to cull 23323464ebd5Sriastradh * the 'off' bits. A bitmap cache as in the gallium/mesa state 23333464ebd5Sriastradh * tracker would improve performance a lot. 23344a49301eSmrg */ 23354a49301eSmrgvoid 23363464ebd5Sriastradh_mesa_meta_Bitmap(struct gl_context *ctx, 23374a49301eSmrg GLint x, GLint y, GLsizei width, GLsizei height, 23384a49301eSmrg const struct gl_pixelstore_attrib *unpack, 23394a49301eSmrg const GLubyte *bitmap1) 23404a49301eSmrg{ 23414a49301eSmrg struct bitmap_state *bitmap = &ctx->Meta->Bitmap; 23424a49301eSmrg struct temp_texture *tex = get_bitmap_temp_texture(ctx); 23434a49301eSmrg const GLenum texIntFormat = GL_ALPHA; 23444a49301eSmrg const struct gl_pixelstore_attrib unpackSave = *unpack; 23453464ebd5Sriastradh GLubyte fg, bg; 23464a49301eSmrg struct vertex verts[4]; 23474a49301eSmrg GLboolean newTex; 23484a49301eSmrg GLubyte *bitmap8; 23494a49301eSmrg 23504a49301eSmrg /* 23514a49301eSmrg * Check if swrast fallback is needed. 23524a49301eSmrg */ 23534a49301eSmrg if (ctx->_ImageTransferState || 235401e04c3fSmrg _mesa_arb_fragment_program_enabled(ctx) || 23554a49301eSmrg ctx->Fog.Enabled || 2356af69d88dSmrg ctx->Texture._MaxEnabledTexImageUnit != -1 || 23574a49301eSmrg width > tex->MaxSize || 23584a49301eSmrg height > tex->MaxSize) { 23594a49301eSmrg _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1); 23604a49301eSmrg return; 23614a49301eSmrg } 23624a49301eSmrg 23633464ebd5Sriastradh if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx)) 23643464ebd5Sriastradh return; 23653464ebd5Sriastradh 23664a49301eSmrg /* Most GL state applies to glBitmap (like blending, stencil, etc), 23674a49301eSmrg * but a there's a few things we need to override: 23684a49301eSmrg */ 2369af69d88dSmrg _mesa_meta_begin(ctx, (MESA_META_ALPHA_TEST | 2370af69d88dSmrg MESA_META_PIXEL_STORE | 2371af69d88dSmrg MESA_META_RASTERIZATION | 2372af69d88dSmrg MESA_META_SHADER | 2373af69d88dSmrg MESA_META_TEXTURE | 2374af69d88dSmrg MESA_META_TRANSFORM | 2375af69d88dSmrg MESA_META_CLIP | 2376af69d88dSmrg MESA_META_VERTEX | 2377af69d88dSmrg MESA_META_VIEWPORT)); 23784a49301eSmrg 237901e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, &bitmap->VAO, &bitmap->buf_obj, false, 238001e04c3fSmrg 3, 2, 4); 23814a49301eSmrg 2382af69d88dSmrg newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); 23834a49301eSmrg 2384af69d88dSmrg /* Silence valgrind warnings about reading uninitialized stack. */ 2385af69d88dSmrg memset(verts, 0, sizeof(verts)); 23864a49301eSmrg 23874a49301eSmrg /* vertex positions, texcoords, colors (after texture allocation!) */ 23884a49301eSmrg { 23894a49301eSmrg const GLfloat x0 = (GLfloat) x; 23904a49301eSmrg const GLfloat y0 = (GLfloat) y; 23914a49301eSmrg const GLfloat x1 = (GLfloat) (x + width); 23924a49301eSmrg const GLfloat y1 = (GLfloat) (y + height); 2393cdc920a0Smrg const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 23944a49301eSmrg GLuint i; 23954a49301eSmrg 23964a49301eSmrg verts[0].x = x0; 23974a49301eSmrg verts[0].y = y0; 23984a49301eSmrg verts[0].z = z; 2399af69d88dSmrg verts[0].tex[0] = 0.0F; 2400af69d88dSmrg verts[0].tex[1] = 0.0F; 24014a49301eSmrg verts[1].x = x1; 24024a49301eSmrg verts[1].y = y0; 24034a49301eSmrg verts[1].z = z; 2404af69d88dSmrg verts[1].tex[0] = tex->Sright; 2405af69d88dSmrg verts[1].tex[1] = 0.0F; 24064a49301eSmrg verts[2].x = x1; 24074a49301eSmrg verts[2].y = y1; 24084a49301eSmrg verts[2].z = z; 2409af69d88dSmrg verts[2].tex[0] = tex->Sright; 2410af69d88dSmrg verts[2].tex[1] = tex->Ttop; 24114a49301eSmrg verts[3].x = x0; 24124a49301eSmrg verts[3].y = y1; 24134a49301eSmrg verts[3].z = z; 2414af69d88dSmrg verts[3].tex[0] = 0.0F; 2415af69d88dSmrg verts[3].tex[1] = tex->Ttop; 24164a49301eSmrg 24174a49301eSmrg for (i = 0; i < 4; i++) { 24184a49301eSmrg verts[i].r = ctx->Current.RasterColor[0]; 24194a49301eSmrg verts[i].g = ctx->Current.RasterColor[1]; 24204a49301eSmrg verts[i].b = ctx->Current.RasterColor[2]; 24214a49301eSmrg verts[i].a = ctx->Current.RasterColor[3]; 24224a49301eSmrg } 24234a49301eSmrg 24244a49301eSmrg /* upload new vertex data */ 242501e04c3fSmrg _mesa_buffer_sub_data(ctx, bitmap->buf_obj, 0, sizeof(verts), verts); 24264a49301eSmrg } 24274a49301eSmrg 24283464ebd5Sriastradh /* choose different foreground/background alpha values */ 24293464ebd5Sriastradh CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]); 24303464ebd5Sriastradh bg = (fg > 127 ? 0 : 255); 24313464ebd5Sriastradh 24324a49301eSmrg bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1); 24333464ebd5Sriastradh if (!bitmap1) { 24343464ebd5Sriastradh _mesa_meta_end(ctx); 24354a49301eSmrg return; 24363464ebd5Sriastradh } 24374a49301eSmrg 2438af69d88dSmrg bitmap8 = malloc(width * height); 24394a49301eSmrg if (bitmap8) { 24403464ebd5Sriastradh memset(bitmap8, bg, width * height); 24414a49301eSmrg _mesa_expand_bitmap(width, height, &unpackSave, bitmap1, 24423464ebd5Sriastradh bitmap8, width, fg); 24434a49301eSmrg 24444a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_TRUE); 24454a49301eSmrg 24464a49301eSmrg _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE); 24473464ebd5Sriastradh _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg)); 24484a49301eSmrg 2449af69d88dSmrg _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, 2450af69d88dSmrg GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); 24514a49301eSmrg 24524a49301eSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 24534a49301eSmrg 24544a49301eSmrg _mesa_set_enable(ctx, tex->Target, GL_FALSE); 24554a49301eSmrg 2456cdc920a0Smrg free(bitmap8); 24574a49301eSmrg } 24584a49301eSmrg 24594a49301eSmrg _mesa_unmap_pbo_source(ctx, &unpackSave); 24604a49301eSmrg 24614a49301eSmrg _mesa_meta_end(ctx); 24624a49301eSmrg} 24634a49301eSmrg 24644a49301eSmrg/** 2465af69d88dSmrg * Compute the texture coordinates for the four vertices of a quad for 246601e04c3fSmrg * drawing a 2D texture image or slice of a cube/3D texture. The offset 246701e04c3fSmrg * and width, height specify a sub-region of the 2D image. 246801e04c3fSmrg * 2469af69d88dSmrg * \param faceTarget GL_TEXTURE_1D/2D/3D or cube face name 2470af69d88dSmrg * \param slice slice of a 1D/2D array texture or 3D texture 247101e04c3fSmrg * \param xoffset X position of sub texture 247201e04c3fSmrg * \param yoffset Y position of sub texture 247301e04c3fSmrg * \param width width of the sub texture image 247401e04c3fSmrg * \param height height of the sub texture image 247501e04c3fSmrg * \param total_width total width of the texture image 247601e04c3fSmrg * \param total_height total height of the texture image 247701e04c3fSmrg * \param total_depth total depth of the texture image 2478af69d88dSmrg * \param coords0/1/2/3 returns the computed texcoords 24794a49301eSmrg */ 2480af69d88dSmrgvoid 2481af69d88dSmrg_mesa_meta_setup_texture_coords(GLenum faceTarget, 2482af69d88dSmrg GLint slice, 248301e04c3fSmrg GLint xoffset, 248401e04c3fSmrg GLint yoffset, 2485af69d88dSmrg GLint width, 2486af69d88dSmrg GLint height, 248701e04c3fSmrg GLint total_width, 248801e04c3fSmrg GLint total_height, 248901e04c3fSmrg GLint total_depth, 2490af69d88dSmrg GLfloat coords0[4], 2491af69d88dSmrg GLfloat coords1[4], 2492af69d88dSmrg GLfloat coords2[4], 2493af69d88dSmrg GLfloat coords3[4]) 24944a49301eSmrg{ 249501e04c3fSmrg float st[4][2]; 2496af69d88dSmrg GLuint i; 249701e04c3fSmrg const float s0 = (float) xoffset / (float) total_width; 249801e04c3fSmrg const float s1 = (float) (xoffset + width) / (float) total_width; 249901e04c3fSmrg const float t0 = (float) yoffset / (float) total_height; 250001e04c3fSmrg const float t1 = (float) (yoffset + height) / (float) total_height; 2501af69d88dSmrg GLfloat r; 25024a49301eSmrg 250301e04c3fSmrg /* setup the reference texcoords */ 250401e04c3fSmrg st[0][0] = s0; 250501e04c3fSmrg st[0][1] = t0; 250601e04c3fSmrg st[1][0] = s1; 250701e04c3fSmrg st[1][1] = t0; 250801e04c3fSmrg st[2][0] = s1; 250901e04c3fSmrg st[2][1] = t1; 251001e04c3fSmrg st[3][0] = s0; 251101e04c3fSmrg st[3][1] = t1; 251201e04c3fSmrg 2513af69d88dSmrg if (faceTarget == GL_TEXTURE_CUBE_MAP_ARRAY) 2514af69d88dSmrg faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice % 6; 25153464ebd5Sriastradh 2516af69d88dSmrg /* Currently all texture targets want the W component to be 1.0. 25174a49301eSmrg */ 2518af69d88dSmrg coords0[3] = 1.0F; 2519af69d88dSmrg coords1[3] = 1.0F; 2520af69d88dSmrg coords2[3] = 1.0F; 2521af69d88dSmrg coords3[3] = 1.0F; 25224a49301eSmrg 2523af69d88dSmrg switch (faceTarget) { 2524af69d88dSmrg case GL_TEXTURE_1D: 2525af69d88dSmrg case GL_TEXTURE_2D: 2526af69d88dSmrg case GL_TEXTURE_3D: 2527af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 2528af69d88dSmrg if (faceTarget == GL_TEXTURE_3D) { 252901e04c3fSmrg assert(slice < total_depth); 253001e04c3fSmrg assert(total_depth >= 1); 253101e04c3fSmrg r = (slice + 0.5f) / total_depth; 2532af69d88dSmrg } 2533af69d88dSmrg else if (faceTarget == GL_TEXTURE_2D_ARRAY) 2534af69d88dSmrg r = (float) slice; 2535af69d88dSmrg else 2536af69d88dSmrg r = 0.0F; 253701e04c3fSmrg coords0[0] = st[0][0]; /* s */ 253801e04c3fSmrg coords0[1] = st[0][1]; /* t */ 2539af69d88dSmrg coords0[2] = r; /* r */ 254001e04c3fSmrg coords1[0] = st[1][0]; 254101e04c3fSmrg coords1[1] = st[1][1]; 2542af69d88dSmrg coords1[2] = r; 254301e04c3fSmrg coords2[0] = st[2][0]; 254401e04c3fSmrg coords2[1] = st[2][1]; 2545af69d88dSmrg coords2[2] = r; 254601e04c3fSmrg coords3[0] = st[3][0]; 254701e04c3fSmrg coords3[1] = st[3][1]; 2548af69d88dSmrg coords3[2] = r; 2549af69d88dSmrg break; 2550af69d88dSmrg case GL_TEXTURE_RECTANGLE_ARB: 255101e04c3fSmrg coords0[0] = (float) xoffset; /* s */ 255201e04c3fSmrg coords0[1] = (float) yoffset; /* t */ 2553af69d88dSmrg coords0[2] = 0.0F; /* r */ 255401e04c3fSmrg coords1[0] = (float) (xoffset + width); 255501e04c3fSmrg coords1[1] = (float) yoffset; 2556af69d88dSmrg coords1[2] = 0.0F; 255701e04c3fSmrg coords2[0] = (float) (xoffset + width); 255801e04c3fSmrg coords2[1] = (float) (yoffset + height); 2559af69d88dSmrg coords2[2] = 0.0F; 256001e04c3fSmrg coords3[0] = (float) xoffset; 256101e04c3fSmrg coords3[1] = (float) (yoffset + height); 2562af69d88dSmrg coords3[2] = 0.0F; 2563af69d88dSmrg break; 2564af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 256501e04c3fSmrg coords0[0] = st[0][0]; /* s */ 2566af69d88dSmrg coords0[1] = (float) slice; /* t */ 2567af69d88dSmrg coords0[2] = 0.0F; /* r */ 256801e04c3fSmrg coords1[0] = st[1][0]; 2569af69d88dSmrg coords1[1] = (float) slice; 2570af69d88dSmrg coords1[2] = 0.0F; 257101e04c3fSmrg coords2[0] = st[2][0]; 2572af69d88dSmrg coords2[1] = (float) slice; 2573af69d88dSmrg coords2[2] = 0.0F; 257401e04c3fSmrg coords3[0] = st[3][0]; 2575af69d88dSmrg coords3[1] = (float) slice; 2576af69d88dSmrg coords3[2] = 0.0F; 2577af69d88dSmrg break; 25784a49301eSmrg 2579af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2580af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2581af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2582af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2583af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2584af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2585af69d88dSmrg /* loop over quad verts */ 2586af69d88dSmrg for (i = 0; i < 4; i++) { 2587af69d88dSmrg /* Compute sc = +/-scale and tc = +/-scale. 2588af69d88dSmrg * Not +/-1 to avoid cube face selection ambiguity near the edges, 2589af69d88dSmrg * though that can still sometimes happen with this scale factor... 2590af69d88dSmrg */ 2591af69d88dSmrg const GLfloat scale = 0.9999f; 2592af69d88dSmrg const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale; 2593af69d88dSmrg const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale; 2594af69d88dSmrg GLfloat *coord; 2595af69d88dSmrg 2596af69d88dSmrg switch (i) { 2597af69d88dSmrg case 0: 2598af69d88dSmrg coord = coords0; 2599af69d88dSmrg break; 2600af69d88dSmrg case 1: 2601af69d88dSmrg coord = coords1; 2602af69d88dSmrg break; 2603af69d88dSmrg case 2: 2604af69d88dSmrg coord = coords2; 2605af69d88dSmrg break; 2606af69d88dSmrg case 3: 2607af69d88dSmrg coord = coords3; 2608af69d88dSmrg break; 2609af69d88dSmrg default: 2610af69d88dSmrg unreachable("not reached"); 2611af69d88dSmrg } 26124a49301eSmrg 2613af69d88dSmrg coord[3] = (float) (slice / 6); 2614af69d88dSmrg 2615af69d88dSmrg switch (faceTarget) { 2616af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2617af69d88dSmrg coord[0] = 1.0f; 2618af69d88dSmrg coord[1] = -tc; 2619af69d88dSmrg coord[2] = -sc; 2620af69d88dSmrg break; 2621af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2622af69d88dSmrg coord[0] = -1.0f; 2623af69d88dSmrg coord[1] = -tc; 2624af69d88dSmrg coord[2] = sc; 2625af69d88dSmrg break; 2626af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2627af69d88dSmrg coord[0] = sc; 2628af69d88dSmrg coord[1] = 1.0f; 2629af69d88dSmrg coord[2] = tc; 2630af69d88dSmrg break; 2631af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2632af69d88dSmrg coord[0] = sc; 2633af69d88dSmrg coord[1] = -1.0f; 2634af69d88dSmrg coord[2] = -tc; 2635af69d88dSmrg break; 2636af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2637af69d88dSmrg coord[0] = sc; 2638af69d88dSmrg coord[1] = -tc; 2639af69d88dSmrg coord[2] = 1.0f; 2640af69d88dSmrg break; 2641af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2642af69d88dSmrg coord[0] = -sc; 2643af69d88dSmrg coord[1] = -tc; 2644af69d88dSmrg coord[2] = -1.0f; 2645af69d88dSmrg break; 2646af69d88dSmrg default: 2647af69d88dSmrg assert(0); 2648af69d88dSmrg } 2649af69d88dSmrg } 2650af69d88dSmrg break; 2651af69d88dSmrg default: 2652af69d88dSmrg assert(!"unexpected target in _mesa_meta_setup_texture_coords()"); 26534a49301eSmrg } 2654af69d88dSmrg} 26554a49301eSmrg 2656af69d88dSmrgstatic struct blit_shader * 2657af69d88dSmrgchoose_blit_shader(GLenum target, struct blit_shader_table *table) 2658af69d88dSmrg{ 2659af69d88dSmrg switch(target) { 2660af69d88dSmrg case GL_TEXTURE_1D: 2661af69d88dSmrg table->sampler_1d.type = "sampler1D"; 2662af69d88dSmrg table->sampler_1d.func = "texture1D"; 2663af69d88dSmrg table->sampler_1d.texcoords = "texCoords.x"; 2664af69d88dSmrg return &table->sampler_1d; 2665af69d88dSmrg case GL_TEXTURE_2D: 2666af69d88dSmrg table->sampler_2d.type = "sampler2D"; 2667af69d88dSmrg table->sampler_2d.func = "texture2D"; 2668af69d88dSmrg table->sampler_2d.texcoords = "texCoords.xy"; 2669af69d88dSmrg return &table->sampler_2d; 2670af69d88dSmrg case GL_TEXTURE_RECTANGLE: 2671af69d88dSmrg table->sampler_rect.type = "sampler2DRect"; 2672af69d88dSmrg table->sampler_rect.func = "texture2DRect"; 2673af69d88dSmrg table->sampler_rect.texcoords = "texCoords.xy"; 2674af69d88dSmrg return &table->sampler_rect; 2675af69d88dSmrg case GL_TEXTURE_3D: 2676af69d88dSmrg /* Code for mipmap generation with 3D textures is not used yet. 2677af69d88dSmrg * It's a sw fallback. 2678af69d88dSmrg */ 2679af69d88dSmrg table->sampler_3d.type = "sampler3D"; 2680af69d88dSmrg table->sampler_3d.func = "texture3D"; 2681af69d88dSmrg table->sampler_3d.texcoords = "texCoords.xyz"; 2682af69d88dSmrg return &table->sampler_3d; 2683af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 2684af69d88dSmrg table->sampler_cubemap.type = "samplerCube"; 2685af69d88dSmrg table->sampler_cubemap.func = "textureCube"; 2686af69d88dSmrg table->sampler_cubemap.texcoords = "texCoords.xyz"; 2687af69d88dSmrg return &table->sampler_cubemap; 2688af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 2689af69d88dSmrg table->sampler_1d_array.type = "sampler1DArray"; 2690af69d88dSmrg table->sampler_1d_array.func = "texture1DArray"; 2691af69d88dSmrg table->sampler_1d_array.texcoords = "texCoords.xy"; 2692af69d88dSmrg return &table->sampler_1d_array; 2693af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 2694af69d88dSmrg table->sampler_2d_array.type = "sampler2DArray"; 2695af69d88dSmrg table->sampler_2d_array.func = "texture2DArray"; 2696af69d88dSmrg table->sampler_2d_array.texcoords = "texCoords.xyz"; 2697af69d88dSmrg return &table->sampler_2d_array; 2698af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 2699af69d88dSmrg table->sampler_cubemap_array.type = "samplerCubeArray"; 2700af69d88dSmrg table->sampler_cubemap_array.func = "textureCubeArray"; 2701af69d88dSmrg table->sampler_cubemap_array.texcoords = "texCoords.xyzw"; 2702af69d88dSmrg return &table->sampler_cubemap_array; 2703af69d88dSmrg default: 2704af69d88dSmrg _mesa_problem(NULL, "Unexpected texture target 0x%x in" 2705af69d88dSmrg " setup_texture_sampler()\n", target); 2706af69d88dSmrg return NULL; 2707af69d88dSmrg } 27084a49301eSmrg} 27094a49301eSmrg 2710af69d88dSmrgvoid 271101e04c3fSmrg_mesa_meta_blit_shader_table_cleanup(struct gl_context *ctx, 271201e04c3fSmrg struct blit_shader_table *table) 2713af69d88dSmrg{ 271401e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_1d.shader_prog, NULL); 271501e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_2d.shader_prog, NULL); 271601e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_3d.shader_prog, NULL); 271701e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_rect.shader_prog, NULL); 271801e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_cubemap.shader_prog, NULL); 271901e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_1d_array.shader_prog, NULL); 272001e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_2d_array.shader_prog, NULL); 272101e04c3fSmrg _mesa_reference_shader_program(ctx, &table->sampler_cubemap_array.shader_prog, NULL); 2722af69d88dSmrg} 27234a49301eSmrg 27244a49301eSmrg/** 2725af69d88dSmrg * Determine the GL data type to use for the temporary image read with 2726af69d88dSmrg * ReadPixels() and passed to Tex[Sub]Image(). 27274a49301eSmrg */ 2728af69d88dSmrgstatic GLenum 2729af69d88dSmrgget_temp_image_type(struct gl_context *ctx, mesa_format format) 27304a49301eSmrg{ 2731af69d88dSmrg const GLenum baseFormat = _mesa_get_format_base_format(format); 2732af69d88dSmrg const GLenum datatype = _mesa_get_format_datatype(format); 2733af69d88dSmrg const GLint format_red_bits = _mesa_get_format_bits(format, GL_RED_BITS); 27344a49301eSmrg 2735af69d88dSmrg switch (baseFormat) { 2736af69d88dSmrg case GL_RGBA: 2737af69d88dSmrg case GL_RGB: 2738af69d88dSmrg case GL_RG: 2739af69d88dSmrg case GL_RED: 2740af69d88dSmrg case GL_ALPHA: 2741af69d88dSmrg case GL_LUMINANCE: 2742af69d88dSmrg case GL_LUMINANCE_ALPHA: 2743af69d88dSmrg case GL_INTENSITY: 2744af69d88dSmrg if (datatype == GL_INT || datatype == GL_UNSIGNED_INT) { 2745af69d88dSmrg return datatype; 2746af69d88dSmrg } else if (format_red_bits <= 8) { 2747af69d88dSmrg return GL_UNSIGNED_BYTE; 2748af69d88dSmrg } else if (format_red_bits <= 16) { 2749af69d88dSmrg return GL_UNSIGNED_SHORT; 2750af69d88dSmrg } 2751af69d88dSmrg return GL_FLOAT; 2752af69d88dSmrg case GL_DEPTH_COMPONENT: 2753af69d88dSmrg if (datatype == GL_FLOAT) 2754af69d88dSmrg return GL_FLOAT; 2755af69d88dSmrg else 2756af69d88dSmrg return GL_UNSIGNED_INT; 2757af69d88dSmrg case GL_DEPTH_STENCIL: 2758af69d88dSmrg if (datatype == GL_FLOAT) 2759af69d88dSmrg return GL_FLOAT_32_UNSIGNED_INT_24_8_REV; 2760af69d88dSmrg else 2761af69d88dSmrg return GL_UNSIGNED_INT_24_8; 2762af69d88dSmrg default: 2763af69d88dSmrg _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()", 276401e04c3fSmrg baseFormat); 2765af69d88dSmrg return 0; 27664a49301eSmrg } 2767af69d88dSmrg} 27684a49301eSmrg 2769af69d88dSmrg/** 2770af69d88dSmrg * Attempts to wrap the destination texture in an FBO and use 2771af69d88dSmrg * glBlitFramebuffer() to implement glCopyTexSubImage(). 2772af69d88dSmrg */ 2773af69d88dSmrgstatic bool 277401e04c3fSmrgcopytexsubimage_using_blit_framebuffer(struct gl_context *ctx, 2775af69d88dSmrg struct gl_texture_image *texImage, 2776af69d88dSmrg GLint xoffset, 2777af69d88dSmrg GLint yoffset, 2778af69d88dSmrg GLint zoffset, 2779af69d88dSmrg struct gl_renderbuffer *rb, 2780af69d88dSmrg GLint x, GLint y, 2781af69d88dSmrg GLsizei width, GLsizei height) 2782af69d88dSmrg{ 278301e04c3fSmrg struct gl_framebuffer *drawFb; 2784af69d88dSmrg bool success = false; 2785af69d88dSmrg GLbitfield mask; 2786af69d88dSmrg GLenum status; 27874a49301eSmrg 2788af69d88dSmrg if (!ctx->Extensions.ARB_framebuffer_object) 2789af69d88dSmrg return false; 27904a49301eSmrg 279101e04c3fSmrg drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 279201e04c3fSmrg if (drawFb == NULL) 279301e04c3fSmrg return false; 27944a49301eSmrg 279501e04c3fSmrg _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); 279601e04c3fSmrg _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer); 27974a49301eSmrg 2798af69d88dSmrg if (rb->_BaseFormat == GL_DEPTH_STENCIL || 2799af69d88dSmrg rb->_BaseFormat == GL_DEPTH_COMPONENT) { 280001e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 280101e04c3fSmrg GL_DEPTH_ATTACHMENT, 280201e04c3fSmrg texImage, zoffset); 2803af69d88dSmrg mask = GL_DEPTH_BUFFER_BIT; 28044a49301eSmrg 2805af69d88dSmrg if (rb->_BaseFormat == GL_DEPTH_STENCIL && 2806af69d88dSmrg texImage->_BaseFormat == GL_DEPTH_STENCIL) { 280701e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 280801e04c3fSmrg GL_STENCIL_ATTACHMENT, 280901e04c3fSmrg texImage, zoffset); 2810af69d88dSmrg mask |= GL_STENCIL_BUFFER_BIT; 2811af69d88dSmrg } 2812af69d88dSmrg _mesa_DrawBuffer(GL_NONE); 2813af69d88dSmrg } else { 281401e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 281501e04c3fSmrg GL_COLOR_ATTACHMENT0, 281601e04c3fSmrg texImage, zoffset); 2817af69d88dSmrg mask = GL_COLOR_BUFFER_BIT; 2818af69d88dSmrg _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); 28194a49301eSmrg } 28204a49301eSmrg 282101e04c3fSmrg status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 2822af69d88dSmrg if (status != GL_FRAMEBUFFER_COMPLETE) 2823af69d88dSmrg goto out; 28244a49301eSmrg 2825af69d88dSmrg ctx->Meta->Blit.no_ctsi_fallback = true; 28263464ebd5Sriastradh 2827af69d88dSmrg /* Since we've bound a new draw framebuffer, we need to update 2828af69d88dSmrg * its derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to 2829af69d88dSmrg * be correct. 2830af69d88dSmrg */ 2831af69d88dSmrg _mesa_update_state(ctx); 28324a49301eSmrg 2833af69d88dSmrg /* We skip the core BlitFramebuffer checks for format consistency, which 2834af69d88dSmrg * are too strict for CopyTexImage. We know meta will be fine with format 2835af69d88dSmrg * changes. 2836af69d88dSmrg */ 283701e04c3fSmrg mask = _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 283801e04c3fSmrg x, y, 2839af69d88dSmrg x + width, y + height, 2840af69d88dSmrg xoffset, yoffset, 2841af69d88dSmrg xoffset + width, yoffset + height, 2842af69d88dSmrg mask, GL_NEAREST); 2843af69d88dSmrg ctx->Meta->Blit.no_ctsi_fallback = false; 2844af69d88dSmrg success = mask == 0x0; 2845af69d88dSmrg 2846af69d88dSmrg out: 284701e04c3fSmrg _mesa_reference_framebuffer(&drawFb, NULL); 2848af69d88dSmrg _mesa_meta_end(ctx); 2849af69d88dSmrg return success; 2850af69d88dSmrg} 28514a49301eSmrg 28524a49301eSmrg/** 2853af69d88dSmrg * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions. 28544a49301eSmrg * Have to be careful with locking and meta state for pixel transfer. 28554a49301eSmrg */ 2856af69d88dSmrgvoid 2857af69d88dSmrg_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, 2858af69d88dSmrg struct gl_texture_image *texImage, 2859af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 2860af69d88dSmrg struct gl_renderbuffer *rb, 2861af69d88dSmrg GLint x, GLint y, 2862af69d88dSmrg GLsizei width, GLsizei height) 28634a49301eSmrg{ 28644a49301eSmrg GLenum format, type; 28654a49301eSmrg GLint bpp; 28664a49301eSmrg void *buf; 28674a49301eSmrg 286801e04c3fSmrg if (copytexsubimage_using_blit_framebuffer(ctx, 2869af69d88dSmrg texImage, 2870af69d88dSmrg xoffset, yoffset, zoffset, 2871af69d88dSmrg rb, 2872af69d88dSmrg x, y, 2873af69d88dSmrg width, height)) { 2874af69d88dSmrg return; 2875af69d88dSmrg } 28764a49301eSmrg 28773464ebd5Sriastradh /* Choose format/type for temporary image buffer */ 2878af69d88dSmrg format = _mesa_get_format_base_format(texImage->TexFormat); 2879af69d88dSmrg if (format == GL_LUMINANCE || 2880af69d88dSmrg format == GL_LUMINANCE_ALPHA || 2881af69d88dSmrg format == GL_INTENSITY) { 2882af69d88dSmrg /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the 2883af69d88dSmrg * temp image buffer because glReadPixels will do L=R+G+B which is 2884af69d88dSmrg * not what we want (should be L=R). 28853464ebd5Sriastradh */ 28863464ebd5Sriastradh format = GL_RGBA; 28873464ebd5Sriastradh } 28883464ebd5Sriastradh 2889af69d88dSmrg type = get_temp_image_type(ctx, texImage->TexFormat); 2890af69d88dSmrg if (_mesa_is_format_integer_color(texImage->TexFormat)) { 2891af69d88dSmrg format = _mesa_base_format_to_integer_format(format); 2892af69d88dSmrg } 28934a49301eSmrg bpp = _mesa_bytes_per_pixel(format, type); 28944a49301eSmrg if (bpp <= 0) { 2895af69d88dSmrg _mesa_problem(ctx, "Bad bpp in _mesa_meta_CopyTexSubImage()"); 28964a49301eSmrg return; 28974a49301eSmrg } 28984a49301eSmrg 28994a49301eSmrg /* 29004a49301eSmrg * Alloc image buffer (XXX could use a PBO) 29014a49301eSmrg */ 2902cdc920a0Smrg buf = malloc(width * height * bpp); 29034a49301eSmrg if (!buf) { 2904af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims); 29054a49301eSmrg return; 29064a49301eSmrg } 29074a49301eSmrg 29084a49301eSmrg /* 29094a49301eSmrg * Read image from framebuffer (disable pixel transfer ops) 29104a49301eSmrg */ 2911af69d88dSmrg _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER); 29124a49301eSmrg ctx->Driver.ReadPixels(ctx, x, y, width, height, 291301e04c3fSmrg format, type, &ctx->Pack, buf); 29144a49301eSmrg _mesa_meta_end(ctx); 29154a49301eSmrg 2916af69d88dSmrg _mesa_update_state(ctx); /* to update pixel transfer state */ 29174a49301eSmrg 29184a49301eSmrg /* 29194a49301eSmrg * Store texture data (with pixel transfer ops) 29204a49301eSmrg */ 2921af69d88dSmrg _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE); 29224a49301eSmrg 2923af69d88dSmrg if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 2924af69d88dSmrg assert(yoffset == 0); 2925af69d88dSmrg ctx->Driver.TexSubImage(ctx, dims, texImage, 2926af69d88dSmrg xoffset, zoffset, 0, width, 1, 1, 2927af69d88dSmrg format, type, buf, &ctx->Unpack); 2928af69d88dSmrg } else { 2929af69d88dSmrg ctx->Driver.TexSubImage(ctx, dims, texImage, 2930af69d88dSmrg xoffset, yoffset, zoffset, width, height, 1, 2931af69d88dSmrg format, type, buf, &ctx->Unpack); 29324a49301eSmrg } 29334a49301eSmrg 2934af69d88dSmrg _mesa_meta_end(ctx); 29354a49301eSmrg 2936cdc920a0Smrg free(buf); 29374a49301eSmrg} 29384a49301eSmrg 2939af69d88dSmrgstatic void 2940af69d88dSmrgmeta_decompress_fbo_cleanup(struct decompress_fbo_state *decompress_fbo) 29414a49301eSmrg{ 294201e04c3fSmrg if (decompress_fbo->fb != NULL) { 294301e04c3fSmrg _mesa_reference_framebuffer(&decompress_fbo->fb, NULL); 294401e04c3fSmrg _mesa_reference_renderbuffer(&decompress_fbo->rb, NULL); 2945af69d88dSmrg } 29464a49301eSmrg 2947af69d88dSmrg memset(decompress_fbo, 0, sizeof(*decompress_fbo)); 2948af69d88dSmrg} 29494a49301eSmrg 2950af69d88dSmrgstatic void 295101e04c3fSmrgmeta_decompress_cleanup(struct gl_context *ctx, 295201e04c3fSmrg struct decompress_state *decompress) 29534a49301eSmrg{ 2954af69d88dSmrg meta_decompress_fbo_cleanup(&decompress->byteFBO); 2955af69d88dSmrg meta_decompress_fbo_cleanup(&decompress->floatFBO); 29564a49301eSmrg 2957af69d88dSmrg if (decompress->VAO != 0) { 2958af69d88dSmrg _mesa_DeleteVertexArrays(1, &decompress->VAO); 295901e04c3fSmrg _mesa_reference_buffer_object(ctx, &decompress->buf_obj, NULL); 2960af69d88dSmrg } 29614a49301eSmrg 296201e04c3fSmrg _mesa_reference_sampler_object(ctx, &decompress->samp_obj, NULL); 29637ec681f3Smrg _mesa_meta_blit_shader_table_cleanup(ctx, &decompress->shaders); 2964af69d88dSmrg 2965af69d88dSmrg memset(decompress, 0, sizeof(*decompress)); 2966af69d88dSmrg} 29674a49301eSmrg 29684a49301eSmrg/** 2969af69d88dSmrg * Decompress a texture image by drawing a quad with the compressed 2970af69d88dSmrg * texture and reading the pixels out of the color buffer. 2971af69d88dSmrg * \param slice which slice of a 3D texture or layer of a 1D/2D texture 2972af69d88dSmrg * \param destFormat format, ala glReadPixels 2973af69d88dSmrg * \param destType type, ala glReadPixels 2974af69d88dSmrg * \param dest destination buffer 2975af69d88dSmrg * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH) 29764a49301eSmrg */ 2977af69d88dSmrgstatic bool 2978af69d88dSmrgdecompress_texture_image(struct gl_context *ctx, 2979af69d88dSmrg struct gl_texture_image *texImage, 2980af69d88dSmrg GLuint slice, 298101e04c3fSmrg GLint xoffset, GLint yoffset, 298201e04c3fSmrg GLsizei width, GLsizei height, 2983af69d88dSmrg GLenum destFormat, GLenum destType, 2984af69d88dSmrg GLvoid *dest) 29854a49301eSmrg{ 2986af69d88dSmrg struct decompress_state *decompress = &ctx->Meta->Decompress; 2987af69d88dSmrg struct decompress_fbo_state *decompress_fbo; 2988af69d88dSmrg struct gl_texture_object *texObj = texImage->TexObject; 2989af69d88dSmrg const GLenum target = texObj->Target; 2990af69d88dSmrg GLenum rbFormat; 2991af69d88dSmrg GLenum faceTarget; 2992af69d88dSmrg struct vertex verts[4]; 299301e04c3fSmrg struct gl_sampler_object *samp_obj_save = NULL; 2994af69d88dSmrg GLenum status; 2995af69d88dSmrg const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader && 2996af69d88dSmrg ctx->Extensions.ARB_fragment_shader; 29974a49301eSmrg 2998af69d88dSmrg switch (_mesa_get_format_datatype(texImage->TexFormat)) { 2999af69d88dSmrg case GL_FLOAT: 3000af69d88dSmrg decompress_fbo = &decompress->floatFBO; 3001af69d88dSmrg rbFormat = GL_RGBA32F; 3002af69d88dSmrg break; 3003af69d88dSmrg case GL_UNSIGNED_NORMALIZED: 3004af69d88dSmrg decompress_fbo = &decompress->byteFBO; 3005af69d88dSmrg rbFormat = GL_RGBA; 3006af69d88dSmrg break; 3007af69d88dSmrg default: 3008af69d88dSmrg return false; 3009af69d88dSmrg } 30104a49301eSmrg 3011af69d88dSmrg if (slice > 0) { 3012af69d88dSmrg assert(target == GL_TEXTURE_3D || 3013af69d88dSmrg target == GL_TEXTURE_2D_ARRAY || 3014af69d88dSmrg target == GL_TEXTURE_CUBE_MAP_ARRAY); 30153464ebd5Sriastradh } 30163464ebd5Sriastradh 3017af69d88dSmrg switch (target) { 3018af69d88dSmrg case GL_TEXTURE_1D: 3019af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 3020af69d88dSmrg assert(!"No compressed 1D textures."); 3021af69d88dSmrg return false; 3022af69d88dSmrg 3023af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 3024af69d88dSmrg faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6); 3025af69d88dSmrg break; 3026af69d88dSmrg 3027af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 3028af69d88dSmrg faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; 3029af69d88dSmrg break; 3030af69d88dSmrg 3031af69d88dSmrg default: 3032af69d88dSmrg faceTarget = target; 3033af69d88dSmrg break; 30344a49301eSmrg } 30354a49301eSmrg 3036af69d88dSmrg _mesa_meta_begin(ctx, MESA_META_ALL & ~(MESA_META_PIXEL_STORE | 3037af69d88dSmrg MESA_META_DRAW_BUFFERS)); 303801e04c3fSmrg _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 3039af69d88dSmrg 304001e04c3fSmrg _mesa_reference_sampler_object(ctx, &samp_obj_save, 304101e04c3fSmrg ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler); 3042af69d88dSmrg 3043af69d88dSmrg /* Create/bind FBO/renderbuffer */ 304401e04c3fSmrg if (decompress_fbo->fb == NULL) { 304501e04c3fSmrg decompress_fbo->rb = ctx->Driver.NewRenderbuffer(ctx, 0xDEADBEEF); 304601e04c3fSmrg if (decompress_fbo->rb == NULL) { 304701e04c3fSmrg _mesa_meta_end(ctx); 304801e04c3fSmrg return false; 304901e04c3fSmrg } 305001e04c3fSmrg 305101e04c3fSmrg decompress_fbo->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 305201e04c3fSmrg if (decompress_fbo->fb == NULL) { 305301e04c3fSmrg _mesa_meta_end(ctx); 305401e04c3fSmrg return false; 305501e04c3fSmrg } 305601e04c3fSmrg 305701e04c3fSmrg _mesa_bind_framebuffers(ctx, decompress_fbo->fb, decompress_fbo->fb); 305801e04c3fSmrg _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, 305901e04c3fSmrg decompress_fbo->rb); 3060af69d88dSmrg } 3061af69d88dSmrg else { 306201e04c3fSmrg _mesa_bind_framebuffers(ctx, decompress_fbo->fb, decompress_fbo->fb); 3063af69d88dSmrg } 3064af69d88dSmrg 3065af69d88dSmrg /* alloc dest surface */ 3066af69d88dSmrg if (width > decompress_fbo->Width || height > decompress_fbo->Height) { 306701e04c3fSmrg _mesa_renderbuffer_storage(ctx, decompress_fbo->rb, rbFormat, 306801e04c3fSmrg width, height, 0, 0); 306901e04c3fSmrg 307001e04c3fSmrg /* Do the full completeness check to recompute 307101e04c3fSmrg * ctx->DrawBuffer->Width/Height. 307201e04c3fSmrg */ 307301e04c3fSmrg ctx->DrawBuffer->_Status = GL_FRAMEBUFFER_UNDEFINED; 307401e04c3fSmrg status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 3075af69d88dSmrg if (status != GL_FRAMEBUFFER_COMPLETE) { 3076af69d88dSmrg /* If the framebuffer isn't complete then we'll leave 3077af69d88dSmrg * decompress_fbo->Width as zero so that it will fail again next time 3078af69d88dSmrg * too */ 3079af69d88dSmrg _mesa_meta_end(ctx); 3080af69d88dSmrg return false; 3081af69d88dSmrg } 3082af69d88dSmrg decompress_fbo->Width = width; 3083af69d88dSmrg decompress_fbo->Height = height; 30844a49301eSmrg } 30854a49301eSmrg 3086af69d88dSmrg if (use_glsl_version) { 308701e04c3fSmrg _mesa_meta_setup_vertex_objects(ctx, &decompress->VAO, 308801e04c3fSmrg &decompress->buf_obj, true, 3089af69d88dSmrg 2, 4, 0); 30904a49301eSmrg 309101e04c3fSmrg _mesa_meta_setup_blit_shader(ctx, target, false, &decompress->shaders); 3092af69d88dSmrg } else { 309301e04c3fSmrg _mesa_meta_setup_ff_tnl_for_blit(ctx, &decompress->VAO, 309401e04c3fSmrg &decompress->buf_obj, 3); 3095af69d88dSmrg } 30964a49301eSmrg 309701e04c3fSmrg if (decompress->samp_obj == NULL) { 309801e04c3fSmrg decompress->samp_obj = ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF); 309901e04c3fSmrg if (decompress->samp_obj == NULL) { 310001e04c3fSmrg _mesa_meta_end(ctx); 310101e04c3fSmrg 310201e04c3fSmrg /* This is a bit lazy. Flag out of memory, and then don't bother to 310301e04c3fSmrg * clean up. Once out of memory is flagged, the only realistic next 310401e04c3fSmrg * move is to destroy the context. That will trigger all the right 310501e04c3fSmrg * clean up. 310601e04c3fSmrg * 310701e04c3fSmrg * Returning true prevents other GetTexImage methods from attempting 310801e04c3fSmrg * anything since they will likely fail too. 310901e04c3fSmrg */ 311001e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 311101e04c3fSmrg return true; 3112af69d88dSmrg } 31134a49301eSmrg 311401e04c3fSmrg /* nearest filtering */ 311501e04c3fSmrg _mesa_set_sampler_filters(ctx, decompress->samp_obj, GL_NEAREST, GL_NEAREST); 311601e04c3fSmrg 311701e04c3fSmrg /* We don't want to encode or decode sRGB values; treat them as linear. */ 311801e04c3fSmrg _mesa_set_sampler_srgb_decode(ctx, decompress->samp_obj, GL_SKIP_DECODE_EXT); 31194a49301eSmrg } 3120af69d88dSmrg 312101e04c3fSmrg _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, decompress->samp_obj); 312201e04c3fSmrg 3123af69d88dSmrg /* Silence valgrind warnings about reading uninitialized stack. */ 3124af69d88dSmrg memset(verts, 0, sizeof(verts)); 3125af69d88dSmrg 312601e04c3fSmrg _mesa_meta_setup_texture_coords(faceTarget, slice, 312701e04c3fSmrg xoffset, yoffset, width, height, 312801e04c3fSmrg texImage->Width, texImage->Height, 312901e04c3fSmrg texImage->Depth, 3130af69d88dSmrg verts[0].tex, 3131af69d88dSmrg verts[1].tex, 3132af69d88dSmrg verts[2].tex, 3133af69d88dSmrg verts[3].tex); 3134af69d88dSmrg 3135af69d88dSmrg /* setup vertex positions */ 3136af69d88dSmrg verts[0].x = -1.0F; 3137af69d88dSmrg verts[0].y = -1.0F; 3138af69d88dSmrg verts[1].x = 1.0F; 3139af69d88dSmrg verts[1].y = -1.0F; 3140af69d88dSmrg verts[2].x = 1.0F; 3141af69d88dSmrg verts[2].y = 1.0F; 3142af69d88dSmrg verts[3].x = -1.0F; 3143af69d88dSmrg verts[3].y = 1.0F; 3144af69d88dSmrg 3145af69d88dSmrg _mesa_set_viewport(ctx, 0, 0, 0, width, height); 3146af69d88dSmrg 3147af69d88dSmrg /* upload new vertex data */ 314801e04c3fSmrg _mesa_buffer_sub_data(ctx, decompress->buf_obj, 0, sizeof(verts), verts); 3149af69d88dSmrg 3150af69d88dSmrg /* setup texture state */ 315101e04c3fSmrg _mesa_bind_texture(ctx, target, texObj); 3152af69d88dSmrg 3153af69d88dSmrg if (!use_glsl_version) 3154af69d88dSmrg _mesa_set_enable(ctx, target, GL_TRUE); 3155af69d88dSmrg 3156af69d88dSmrg { 3157af69d88dSmrg /* save texture object state */ 31587ec681f3Smrg const GLint baseLevelSave = texObj->Attrib.BaseLevel; 31597ec681f3Smrg const GLint maxLevelSave = texObj->Attrib.MaxLevel; 3160af69d88dSmrg 3161af69d88dSmrg /* restrict sampling to the texture level of interest */ 3162af69d88dSmrg if (target != GL_TEXTURE_RECTANGLE_ARB) { 316301e04c3fSmrg _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL, 316401e04c3fSmrg (GLint *) &texImage->Level, false); 316501e04c3fSmrg _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, 316601e04c3fSmrg (GLint *) &texImage->Level, false); 3167af69d88dSmrg } 3168af69d88dSmrg 3169af69d88dSmrg /* render quad w/ texture into renderbuffer */ 3170af69d88dSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 31717ec681f3Smrg 3172af69d88dSmrg /* Restore texture object state, the texture binding will 3173af69d88dSmrg * be restored by _mesa_meta_end(). 3174af69d88dSmrg */ 3175af69d88dSmrg if (target != GL_TEXTURE_RECTANGLE_ARB) { 317601e04c3fSmrg _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL, 317701e04c3fSmrg &baseLevelSave, false); 317801e04c3fSmrg _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, 317901e04c3fSmrg &maxLevelSave, false); 3180af69d88dSmrg } 3181af69d88dSmrg 31824a49301eSmrg } 3183af69d88dSmrg 3184af69d88dSmrg /* read pixels from renderbuffer */ 3185af69d88dSmrg { 3186af69d88dSmrg GLenum baseTexFormat = texImage->_BaseFormat; 318701e04c3fSmrg GLenum destBaseFormat = _mesa_unpack_format_to_base_format(destFormat); 3188af69d88dSmrg 3189af69d88dSmrg /* The pixel transfer state will be set to default values at this point 3190af69d88dSmrg * (see MESA_META_PIXEL_TRANSFER) so pixel transfer ops are effectively 3191af69d88dSmrg * turned off (as required by glGetTexImage) but we need to handle some 3192af69d88dSmrg * special cases. In particular, single-channel texture values are 3193af69d88dSmrg * returned as red and two-channel texture values are returned as 3194af69d88dSmrg * red/alpha. 3195af69d88dSmrg */ 319601e04c3fSmrg if (_mesa_need_luminance_to_rgb_conversion(baseTexFormat, 319701e04c3fSmrg destBaseFormat) || 3198af69d88dSmrg /* If we're reading back an RGB(A) texture (using glGetTexImage) as 319901e04c3fSmrg * luminance then we need to return L=tex(R). 320001e04c3fSmrg */ 320101e04c3fSmrg _mesa_need_rgb_to_luminance_conversion(baseTexFormat, 320201e04c3fSmrg destBaseFormat)) { 3203af69d88dSmrg /* Green and blue must be zero */ 3204af69d88dSmrg _mesa_PixelTransferf(GL_GREEN_SCALE, 0.0f); 3205af69d88dSmrg _mesa_PixelTransferf(GL_BLUE_SCALE, 0.0f); 3206af69d88dSmrg } 3207af69d88dSmrg 3208af69d88dSmrg _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest); 32094a49301eSmrg } 32104a49301eSmrg 3211af69d88dSmrg /* disable texture unit */ 3212af69d88dSmrg if (!use_glsl_version) 3213af69d88dSmrg _mesa_set_enable(ctx, target, GL_FALSE); 32144a49301eSmrg 321501e04c3fSmrg _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save); 321601e04c3fSmrg _mesa_reference_sampler_object(ctx, &samp_obj_save, NULL); 32174a49301eSmrg 3218af69d88dSmrg _mesa_meta_end(ctx); 32194a49301eSmrg 3220af69d88dSmrg return true; 32214a49301eSmrg} 32224a49301eSmrg 32234a49301eSmrg 3224af69d88dSmrg/** 3225af69d88dSmrg * This is just a wrapper around _mesa_get_tex_image() and 3226af69d88dSmrg * decompress_texture_image(). Meta functions should not be directly called 3227af69d88dSmrg * from core Mesa. 3228af69d88dSmrg */ 32294a49301eSmrgvoid 323001e04c3fSmrg_mesa_meta_GetTexSubImage(struct gl_context *ctx, 323101e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 323201e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 323301e04c3fSmrg GLenum format, GLenum type, GLvoid *pixels, 323401e04c3fSmrg struct gl_texture_image *texImage) 32354a49301eSmrg{ 3236af69d88dSmrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 3237af69d88dSmrg GLuint slice; 323801e04c3fSmrg bool result = true; 3239af69d88dSmrg 324001e04c3fSmrg for (slice = 0; slice < depth; slice++) { 3241af69d88dSmrg void *dst; 324201e04c3fSmrg /* Section 8.11.4 (Texture Image Queries) of the GL 4.5 spec says: 324301e04c3fSmrg * 324401e04c3fSmrg * "For three-dimensional, two-dimensional array, cube map array, 324501e04c3fSmrg * and cube map textures pixel storage operations are applied as 324601e04c3fSmrg * if the image were two-dimensional, except that the additional 324701e04c3fSmrg * pixel storage state values PACK_IMAGE_HEIGHT and 324801e04c3fSmrg * PACK_SKIP_IMAGES are applied. The correspondence of texels to 324901e04c3fSmrg * memory locations is as defined for TexImage3D in section 8.5." 325001e04c3fSmrg */ 325101e04c3fSmrg switch (texImage->TexObject->Target) { 325201e04c3fSmrg case GL_TEXTURE_3D: 325301e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 325401e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 325501e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: { 3256af69d88dSmrg /* Setup pixel packing. SkipPixels and SkipRows will be applied 3257af69d88dSmrg * in the decompress_texture_image() function's call to 3258af69d88dSmrg * glReadPixels but we need to compute the dest slice's address 3259af69d88dSmrg * here (according to SkipImages and ImageHeight). 3260af69d88dSmrg */ 3261af69d88dSmrg struct gl_pixelstore_attrib packing = ctx->Pack; 3262af69d88dSmrg packing.SkipPixels = 0; 3263af69d88dSmrg packing.SkipRows = 0; 326401e04c3fSmrg dst = _mesa_image_address3d(&packing, pixels, width, height, 326501e04c3fSmrg format, type, slice, 0, 0); 326601e04c3fSmrg break; 3267af69d88dSmrg } 326801e04c3fSmrg default: 3269af69d88dSmrg dst = pixels; 327001e04c3fSmrg break; 3271af69d88dSmrg } 3272af69d88dSmrg result = decompress_texture_image(ctx, texImage, slice, 327301e04c3fSmrg xoffset, yoffset, width, height, 3274af69d88dSmrg format, type, dst); 3275af69d88dSmrg if (!result) 3276af69d88dSmrg break; 3277af69d88dSmrg } 32784a49301eSmrg 3279af69d88dSmrg if (result) 3280af69d88dSmrg return; 3281af69d88dSmrg } 32824a49301eSmrg 328301e04c3fSmrg _mesa_GetTexSubImage_sw(ctx, xoffset, yoffset, zoffset, 328401e04c3fSmrg width, height, depth, format, type, pixels, texImage); 32854a49301eSmrg} 32864a49301eSmrg 32874a49301eSmrg 3288af69d88dSmrg/** 3289af69d88dSmrg * Meta implementation of ctx->Driver.DrawTex() in terms 3290af69d88dSmrg * of polygon rendering. 3291af69d88dSmrg */ 32924a49301eSmrgvoid 3293af69d88dSmrg_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, 3294af69d88dSmrg GLfloat width, GLfloat height) 32954a49301eSmrg{ 3296af69d88dSmrg struct drawtex_state *drawtex = &ctx->Meta->DrawTex; 3297af69d88dSmrg struct vertex { 3298af69d88dSmrg GLfloat x, y, z, st[MAX_TEXTURE_UNITS][2]; 3299af69d88dSmrg }; 3300af69d88dSmrg struct vertex verts[4]; 3301af69d88dSmrg GLuint i; 33024a49301eSmrg 3303af69d88dSmrg _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 3304af69d88dSmrg MESA_META_SHADER | 3305af69d88dSmrg MESA_META_TRANSFORM | 3306af69d88dSmrg MESA_META_VERTEX | 3307af69d88dSmrg MESA_META_VIEWPORT)); 3308af69d88dSmrg 3309af69d88dSmrg if (drawtex->VAO == 0) { 3310af69d88dSmrg /* one-time setup */ 331101e04c3fSmrg struct gl_vertex_array_object *array_obj; 3312af69d88dSmrg 3313af69d88dSmrg /* create vertex array object */ 3314af69d88dSmrg _mesa_GenVertexArrays(1, &drawtex->VAO); 3315af69d88dSmrg _mesa_BindVertexArray(drawtex->VAO); 3316af69d88dSmrg 331701e04c3fSmrg array_obj = _mesa_lookup_vao(ctx, drawtex->VAO); 331801e04c3fSmrg assert(array_obj != NULL); 331901e04c3fSmrg 3320af69d88dSmrg /* create vertex array buffer */ 332101e04c3fSmrg drawtex->buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF); 332201e04c3fSmrg if (drawtex->buf_obj == NULL) 332301e04c3fSmrg return; 3324af69d88dSmrg 332501e04c3fSmrg _mesa_buffer_data(ctx, drawtex->buf_obj, GL_NONE, sizeof(verts), verts, 332601e04c3fSmrg GL_DYNAMIC_DRAW, __func__); 3327af69d88dSmrg 3328af69d88dSmrg /* setup vertex arrays */ 33297ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 333001e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_POS, 333101e04c3fSmrg 3, GL_FLOAT, GL_RGBA, GL_FALSE, 333201e04c3fSmrg GL_FALSE, GL_FALSE, 333301e04c3fSmrg offsetof(struct vertex, x)); 333401e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_POS, 33357ec681f3Smrg drawtex->buf_obj, 0, sizeof(struct vertex), 33367ec681f3Smrg false, false); 333701e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_POS); 333801e04c3fSmrg 333901e04c3fSmrg 3340af69d88dSmrg for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 33417ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 334201e04c3fSmrg _mesa_update_array_format(ctx, array_obj, VERT_ATTRIB_TEX(i), 334301e04c3fSmrg 2, GL_FLOAT, GL_RGBA, GL_FALSE, 334401e04c3fSmrg GL_FALSE, GL_FALSE, 334501e04c3fSmrg offsetof(struct vertex, st[i])); 334601e04c3fSmrg _mesa_bind_vertex_buffer(ctx, array_obj, VERT_ATTRIB_TEX(i), 33477ec681f3Smrg drawtex->buf_obj, 0, sizeof(struct vertex), 33487ec681f3Smrg false, false); 334901e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, array_obj, VERT_ATTRIB_TEX(i)); 3350af69d88dSmrg } 3351af69d88dSmrg } 3352af69d88dSmrg else { 3353af69d88dSmrg _mesa_BindVertexArray(drawtex->VAO); 33544a49301eSmrg } 33554a49301eSmrg 3356af69d88dSmrg /* vertex positions, texcoords */ 3357af69d88dSmrg { 3358af69d88dSmrg const GLfloat x1 = x + width; 3359af69d88dSmrg const GLfloat y1 = y + height; 3360af69d88dSmrg 33617ec681f3Smrg z = SATURATE(z); 3362af69d88dSmrg z = invert_z(z); 3363af69d88dSmrg 3364af69d88dSmrg verts[0].x = x; 3365af69d88dSmrg verts[0].y = y; 3366af69d88dSmrg verts[0].z = z; 3367af69d88dSmrg 3368af69d88dSmrg verts[1].x = x1; 3369af69d88dSmrg verts[1].y = y; 3370af69d88dSmrg verts[1].z = z; 3371af69d88dSmrg 3372af69d88dSmrg verts[2].x = x1; 3373af69d88dSmrg verts[2].y = y1; 3374af69d88dSmrg verts[2].z = z; 3375af69d88dSmrg 3376af69d88dSmrg verts[3].x = x; 3377af69d88dSmrg verts[3].y = y1; 3378af69d88dSmrg verts[3].z = z; 3379af69d88dSmrg 3380af69d88dSmrg for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 3381af69d88dSmrg const struct gl_texture_object *texObj; 3382af69d88dSmrg const struct gl_texture_image *texImage; 3383af69d88dSmrg GLfloat s, t, s1, t1; 3384af69d88dSmrg GLuint tw, th; 3385af69d88dSmrg 3386af69d88dSmrg if (!ctx->Texture.Unit[i]._Current) { 3387af69d88dSmrg GLuint j; 3388af69d88dSmrg for (j = 0; j < 4; j++) { 3389af69d88dSmrg verts[j].st[i][0] = 0.0f; 3390af69d88dSmrg verts[j].st[i][1] = 0.0f; 3391af69d88dSmrg } 3392af69d88dSmrg continue; 3393af69d88dSmrg } 33944a49301eSmrg 3395af69d88dSmrg texObj = ctx->Texture.Unit[i]._Current; 33967ec681f3Smrg texImage = texObj->Image[0][texObj->Attrib.BaseLevel]; 3397af69d88dSmrg tw = texImage->Width2; 3398af69d88dSmrg th = texImage->Height2; 3399af69d88dSmrg 3400af69d88dSmrg s = (GLfloat) texObj->CropRect[0] / tw; 3401af69d88dSmrg t = (GLfloat) texObj->CropRect[1] / th; 3402af69d88dSmrg s1 = (GLfloat) (texObj->CropRect[0] + texObj->CropRect[2]) / tw; 3403af69d88dSmrg t1 = (GLfloat) (texObj->CropRect[1] + texObj->CropRect[3]) / th; 3404af69d88dSmrg 3405af69d88dSmrg verts[0].st[i][0] = s; 3406af69d88dSmrg verts[0].st[i][1] = t; 3407af69d88dSmrg 3408af69d88dSmrg verts[1].st[i][0] = s1; 3409af69d88dSmrg verts[1].st[i][1] = t; 3410af69d88dSmrg 3411af69d88dSmrg verts[2].st[i][0] = s1; 3412af69d88dSmrg verts[2].st[i][1] = t1; 3413af69d88dSmrg 3414af69d88dSmrg verts[3].st[i][0] = s; 3415af69d88dSmrg verts[3].st[i][1] = t1; 3416af69d88dSmrg } 3417af69d88dSmrg 341801e04c3fSmrg _mesa_buffer_sub_data(ctx, drawtex->buf_obj, 0, sizeof(verts), verts); 3419af69d88dSmrg } 3420af69d88dSmrg 3421af69d88dSmrg _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 34224a49301eSmrg 34234a49301eSmrg _mesa_meta_end(ctx); 3424af69d88dSmrg} 34254a49301eSmrg 3426af69d88dSmrgstatic bool 3427af69d88dSmrgcleartexsubimage_color(struct gl_context *ctx, 3428af69d88dSmrg struct gl_texture_image *texImage, 3429af69d88dSmrg const GLvoid *clearValue, 3430af69d88dSmrg GLint zoffset) 3431af69d88dSmrg{ 3432af69d88dSmrg mesa_format format; 3433af69d88dSmrg union gl_color_union colorValue; 3434af69d88dSmrg GLenum datatype; 3435af69d88dSmrg GLenum status; 3436af69d88dSmrg 343701e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 343801e04c3fSmrg GL_COLOR_ATTACHMENT0, 343901e04c3fSmrg texImage, zoffset); 3440af69d88dSmrg 344101e04c3fSmrg status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 3442af69d88dSmrg if (status != GL_FRAMEBUFFER_COMPLETE) 3443af69d88dSmrg return false; 3444af69d88dSmrg 3445af69d88dSmrg /* We don't want to apply an sRGB conversion so override the format */ 3446af69d88dSmrg format = _mesa_get_srgb_format_linear(texImage->TexFormat); 3447af69d88dSmrg datatype = _mesa_get_format_datatype(format); 3448af69d88dSmrg 3449af69d88dSmrg switch (datatype) { 3450af69d88dSmrg case GL_UNSIGNED_INT: 3451af69d88dSmrg case GL_INT: 3452af69d88dSmrg if (clearValue) 3453af69d88dSmrg _mesa_unpack_uint_rgba_row(format, 1, clearValue, 3454af69d88dSmrg (GLuint (*)[4]) colorValue.ui); 3455af69d88dSmrg else 3456af69d88dSmrg memset(&colorValue, 0, sizeof colorValue); 3457af69d88dSmrg if (datatype == GL_INT) 3458af69d88dSmrg _mesa_ClearBufferiv(GL_COLOR, 0, colorValue.i); 3459af69d88dSmrg else 3460af69d88dSmrg _mesa_ClearBufferuiv(GL_COLOR, 0, colorValue.ui); 3461af69d88dSmrg break; 3462af69d88dSmrg default: 3463af69d88dSmrg if (clearValue) 3464af69d88dSmrg _mesa_unpack_rgba_row(format, 1, clearValue, 3465af69d88dSmrg (GLfloat (*)[4]) colorValue.f); 3466af69d88dSmrg else 3467af69d88dSmrg memset(&colorValue, 0, sizeof colorValue); 3468af69d88dSmrg _mesa_ClearBufferfv(GL_COLOR, 0, colorValue.f); 3469af69d88dSmrg break; 3470af69d88dSmrg } 3471af69d88dSmrg 3472af69d88dSmrg return true; 34734a49301eSmrg} 34744a49301eSmrg 3475af69d88dSmrgstatic bool 3476af69d88dSmrgcleartexsubimage_depth_stencil(struct gl_context *ctx, 3477af69d88dSmrg struct gl_texture_image *texImage, 3478af69d88dSmrg const GLvoid *clearValue, 3479af69d88dSmrg GLint zoffset) 3480af69d88dSmrg{ 348101e04c3fSmrg GLint stencilValue = 0; 348201e04c3fSmrg GLfloat depthValue = 0.0f; 3483af69d88dSmrg GLenum status; 34844a49301eSmrg 348501e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 348601e04c3fSmrg GL_DEPTH_ATTACHMENT, 348701e04c3fSmrg texImage, zoffset); 3488af69d88dSmrg 3489af69d88dSmrg if (texImage->_BaseFormat == GL_DEPTH_STENCIL) 349001e04c3fSmrg _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 349101e04c3fSmrg GL_STENCIL_ATTACHMENT, 349201e04c3fSmrg texImage, zoffset); 3493af69d88dSmrg 349401e04c3fSmrg status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 3495af69d88dSmrg if (status != GL_FRAMEBUFFER_COMPLETE) 3496af69d88dSmrg return false; 3497af69d88dSmrg 3498af69d88dSmrg if (clearValue) { 3499af69d88dSmrg GLuint depthStencilValue[2]; 3500af69d88dSmrg 3501af69d88dSmrg /* Convert the clearValue from whatever format it's in to a floating 3502af69d88dSmrg * point value for the depth and an integer value for the stencil index 3503af69d88dSmrg */ 350401e04c3fSmrg if (texImage->_BaseFormat == GL_DEPTH_STENCIL) { 350501e04c3fSmrg _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat, 350601e04c3fSmrg 1, /* n */ 350701e04c3fSmrg clearValue, 350801e04c3fSmrg depthStencilValue); 350901e04c3fSmrg /* We need a memcpy here instead of a cast because we need to 351001e04c3fSmrg * reinterpret the bytes as a float rather than converting it 351101e04c3fSmrg */ 351201e04c3fSmrg memcpy(&depthValue, depthStencilValue, sizeof depthValue); 351301e04c3fSmrg stencilValue = depthStencilValue[1] & 0xff; 351401e04c3fSmrg } else { 351501e04c3fSmrg _mesa_unpack_float_z_row(texImage->TexFormat, 1 /* n */, 351601e04c3fSmrg clearValue, &depthValue); 351701e04c3fSmrg } 3518af69d88dSmrg } 3519af69d88dSmrg 3520af69d88dSmrg if (texImage->_BaseFormat == GL_DEPTH_STENCIL) 3521af69d88dSmrg _mesa_ClearBufferfi(GL_DEPTH_STENCIL, 0, depthValue, stencilValue); 3522af69d88dSmrg else 3523af69d88dSmrg _mesa_ClearBufferfv(GL_DEPTH, 0, &depthValue); 3524af69d88dSmrg 3525af69d88dSmrg return true; 3526af69d88dSmrg} 3527af69d88dSmrg 3528af69d88dSmrgstatic bool 3529af69d88dSmrgcleartexsubimage_for_zoffset(struct gl_context *ctx, 3530af69d88dSmrg struct gl_texture_image *texImage, 3531af69d88dSmrg GLint zoffset, 3532af69d88dSmrg const GLvoid *clearValue) 35334a49301eSmrg{ 353401e04c3fSmrg struct gl_framebuffer *drawFb; 3535af69d88dSmrg bool success; 35364a49301eSmrg 353701e04c3fSmrg drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 353801e04c3fSmrg if (drawFb == NULL) 353901e04c3fSmrg return false; 354001e04c3fSmrg 354101e04c3fSmrg _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer); 3542af69d88dSmrg 3543af69d88dSmrg switch(texImage->_BaseFormat) { 3544af69d88dSmrg case GL_DEPTH_STENCIL: 3545af69d88dSmrg case GL_DEPTH_COMPONENT: 3546af69d88dSmrg success = cleartexsubimage_depth_stencil(ctx, texImage, 3547af69d88dSmrg clearValue, zoffset); 3548af69d88dSmrg break; 3549af69d88dSmrg default: 3550af69d88dSmrg success = cleartexsubimage_color(ctx, texImage, clearValue, zoffset); 3551af69d88dSmrg break; 35524a49301eSmrg } 35534a49301eSmrg 355401e04c3fSmrg _mesa_reference_framebuffer(&drawFb, NULL); 3555af69d88dSmrg 3556af69d88dSmrg return success; 3557af69d88dSmrg} 3558af69d88dSmrg 3559af69d88dSmrgstatic bool 3560af69d88dSmrgcleartexsubimage_using_fbo(struct gl_context *ctx, 3561af69d88dSmrg struct gl_texture_image *texImage, 3562af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 3563af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 3564af69d88dSmrg const GLvoid *clearValue) 3565af69d88dSmrg{ 3566af69d88dSmrg bool success = true; 3567af69d88dSmrg GLint z; 35684a49301eSmrg 3569af69d88dSmrg _mesa_meta_begin(ctx, 3570af69d88dSmrg MESA_META_SCISSOR | 3571af69d88dSmrg MESA_META_COLOR_MASK | 3572af69d88dSmrg MESA_META_DITHER | 3573af69d88dSmrg MESA_META_FRAMEBUFFER_SRGB); 3574af69d88dSmrg 357501e04c3fSmrg _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 3576af69d88dSmrg _mesa_set_enable(ctx, GL_DITHER, GL_FALSE); 3577af69d88dSmrg 3578af69d88dSmrg _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE); 3579af69d88dSmrg _mesa_Scissor(xoffset, yoffset, width, height); 3580af69d88dSmrg 3581af69d88dSmrg for (z = zoffset; z < zoffset + depth; z++) { 3582af69d88dSmrg if (!cleartexsubimage_for_zoffset(ctx, texImage, z, clearValue)) { 3583af69d88dSmrg success = false; 3584af69d88dSmrg break; 3585af69d88dSmrg } 3586af69d88dSmrg } 35874a49301eSmrg 35884a49301eSmrg _mesa_meta_end(ctx); 35894a49301eSmrg 3590af69d88dSmrg return success; 3591af69d88dSmrg} 3592af69d88dSmrg 3593af69d88dSmrgextern void 3594af69d88dSmrg_mesa_meta_ClearTexSubImage(struct gl_context *ctx, 3595af69d88dSmrg struct gl_texture_image *texImage, 3596af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 3597af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 3598af69d88dSmrg const GLvoid *clearValue) 3599af69d88dSmrg{ 3600af69d88dSmrg bool res; 3601af69d88dSmrg 3602af69d88dSmrg res = cleartexsubimage_using_fbo(ctx, texImage, 3603af69d88dSmrg xoffset, yoffset, zoffset, 3604af69d88dSmrg width, height, depth, 3605af69d88dSmrg clearValue); 3606af69d88dSmrg 3607af69d88dSmrg if (res) 3608af69d88dSmrg return; 3609af69d88dSmrg 3610af69d88dSmrg _mesa_warning(ctx, 3611af69d88dSmrg "Falling back to mapping the texture in " 3612af69d88dSmrg "glClearTexSubImage\n"); 3613af69d88dSmrg 3614af69d88dSmrg _mesa_store_cleartexsubimage(ctx, texImage, 3615af69d88dSmrg xoffset, yoffset, zoffset, 3616af69d88dSmrg width, height, depth, 3617af69d88dSmrg clearValue); 36184a49301eSmrg} 3619