st_cb_drawpixels.c revision e62530a6c00da71c0f7bf1f4c425fe6c5b452df6
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/************************************************************************** 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * All Rights Reserved. 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Permission is hereby granted, free of charge, to any person obtaining a 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * copy of this software and associated documentation files (the 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * "Software"), to deal in the Software without restriction, including 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * without limitation the rights to use, copy, modify, merge, publish, 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * distribute, sub license, and/or sell copies of the Software, and to 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * permit persons to whom the Software is furnished to do so, subject to 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the following conditions: 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The above copyright notice and this permission notice (including the 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * next paragraph) shall be included in all copies or substantial portions 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of the Software. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown **************************************************************************/ 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Authors: 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Brian Paul 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/imports.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/image.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/bufferobj.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/macros.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/mfeatures.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/mtypes.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/pack.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/pbo.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/texformat.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main/texstore.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "program/program.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "program/prog_print.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "program/prog_instruction.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_atom.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_atom_constbuf.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_cb_drawpixels.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_cb_readpixels.h" 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_cb_fbo.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_context.h" 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_debug.h" 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_format.h" 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_program.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "st_texture.h" 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pipe/p_context.h" 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pipe/p_defines.h" 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tgsi/tgsi_ureg.h" 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "util/u_draw_quad.h" 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "util/u_format.h" 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "util/u_inlines.h" 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "util/u_math.h" 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "util/u_tile.h" 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cso_cache/cso_context.h" 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if FEATURE_drawpix 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Check if the given program is: 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 0: MOVE result.color, fragment.color; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1: END; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic GLboolean 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownis_passthrough_program(const struct gl_fragment_program *prog) 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (prog->Base.NumInstructions == 2) { 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct prog_instruction *inst = prog->Base.Instructions; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (inst[0].Opcode == OPCODE_MOV && 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[1].Opcode == OPCODE_END && 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].DstReg.File == PROGRAM_OUTPUT && 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].DstReg.Index == FRAG_RESULT_COLOR && 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].DstReg.WriteMask == WRITEMASK_XYZW && 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].SrcReg[0].File == PROGRAM_INPUT && 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 && 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_TRUE; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_FALSE; 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Make fragment shader for glDraw/CopyPixels. This shader is made 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * by combining the pixel transfer shader with the user-defined shader. 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * \param fpIn the current/incoming fragment program 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * \param fpOut returns the combined fragment program 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownst_make_drawpix_fragment_program(struct st_context *st, 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_fragment_program *fpIn, 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_fragment_program **fpOut) 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_program *newProg; 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_passthrough_program(fpIn)) { 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &st->pixel_xfer.program->Base); 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* debug */ 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("Base program:\n"); 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _mesa_print_program(&fpIn->Base); 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("DrawPix program:\n"); 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _mesa_print_program(&st->pixel_xfer.program->Base.Base); 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newProg = _mesa_combine_programs(st->ctx, 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &st->pixel_xfer.program->Base.Base, 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &fpIn->Base); 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* debug */ 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("Combined DrawPixels program:\n"); 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _mesa_print_program(newProg); 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("InputsRead: 0x%x\n", newProg->InputsRead); 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _mesa_print_parameter_list(newProg->Parameters); 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *fpOut = (struct gl_fragment_program *) newProg; 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create fragment program that does a TEX() instruction to get a Z and/or 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Pass fragment color through as-is. 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * \return pointer to the gl_fragment program 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct gl_fragment_program * 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownst_make_drawpix_z_stencil_program(struct st_context *st, 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLboolean write_depth, 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLboolean write_stencil) 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_context *ctx = st->ctx; 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_program *p; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_fragment_program *fp; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLuint ic = 0; 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const GLuint shaderIndex = write_depth * 2 + write_stencil; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(shaderIndex < Elements(st->drawpix.shaders)); 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->drawpix.shaders[shaderIndex]) { 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* already have the proper shader */ 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return st->drawpix.shaders[shaderIndex]; 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create shader now 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!p) 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->NumInstructions = write_depth ? 2 : 1; 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->NumInstructions += write_stencil ? 1 : 0; 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!p->Instructions) { 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Driver.DeleteProgram(ctx, p); 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _mesa_init_instructions(p->Instructions, p->NumInstructions); 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (write_depth) { 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */ 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].Opcode = OPCODE_TEX; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].TexSrcUnit = 0; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ic++; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (write_stencil) { 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */ 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].Opcode = OPCODE_TEX; 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL; 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y; 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].TexSrcUnit = 1; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ic++; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* END; */ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->Instructions[ic++].Opcode = OPCODE_END; 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(ic == p->NumInstructions); 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->OutputsWritten = 0; 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (write_depth) 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH); 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (write_stencil) 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL); 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (write_stencil) 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p->SamplersUsed |= 1 << 1; 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fp = (struct gl_fragment_program *) p; 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* save the new shader */ 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->drawpix.shaders[shaderIndex] = fp; 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fp; 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create a simple vertex shader that just passes through the 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * vertex position and texcoord (and optionally, color). 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void * 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmake_passthrough_vertex_shader(struct st_context *st, 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLboolean passColor) 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!st->drawpix.vert_shaders[passColor]) { 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ureg == NULL) 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* MOV result.pos, vertex.pos; */ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_MOV(ureg, 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_vs_input( ureg, 0 )); 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* MOV result.texcoord0, vertex.attr[1]; */ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_MOV(ureg, 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_vs_input( ureg, 1 )); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (passColor) { 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* MOV result.color0, vertex.attr[2]; */ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_MOV(ureg, 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_DECL_vs_input( ureg, 2 )); 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_END( ureg ); 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->drawpix.vert_shaders[passColor] = 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ureg_create_shader_and_destroy( ureg, st->pipe ); 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return st->drawpix.vert_shaders[passColor]; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return a texture base format for drawing/copying an image 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of the given format. 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic GLenum 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbase_format(GLenum format) 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (format) { 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_DEPTH_COMPONENT: 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_DEPTH_COMPONENT; 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_DEPTH_STENCIL: 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_DEPTH_STENCIL; 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_STENCIL_INDEX: 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_STENCIL_INDEX; 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return a texture internalFormat for drawing/copying an image 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of the given format and type. 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic GLenum 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninternal_format(struct gl_context *ctx, GLenum format, GLenum type) 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (format) { 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_DEPTH_COMPONENT: 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_DEPTH_COMPONENT; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_DEPTH_STENCIL: 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_DEPTH_STENCIL; 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_STENCIL_INDEX: 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_STENCIL_INDEX; 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (_mesa_is_integer_format(format)) { 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (type) { 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_BYTE: 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA8I; 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_BYTE: 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA8UI; 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_SHORT: 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA16I; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT: 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA16UI; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_INT: 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA32I; 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT: 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA32UI; 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(0 && "Unexpected type in internal_format()"); 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA_INTEGER; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (type) { 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_BYTE: 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_8_8_8_8: 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_8_8_8_8_REV: 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA8; 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_BYTE_3_3_2: 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_BYTE_2_3_3_REV: 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_4_4_4_4: 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_4_4_4_4_REV: 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA4; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_5_6_5: 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_5_6_5_REV: 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_5_5_5_1: 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT_1_5_5_5_REV: 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGB5_A1; 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_10_10_10_2: 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_2_10_10_10_REV: 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGB10_A2; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_SHORT: 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT: 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGBA16; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_BYTE: 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_SHORT: 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_INT: 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_HALF_FLOAT_ARB: 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.ARB_texture_float ? GL_RGBA16F : 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_FLOAT: 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_DOUBLE: 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.ARB_texture_float ? GL_RGBA32F : 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_5_9_9_9_REV: 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(ctx->Extensions.EXT_texture_shared_exponent); 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_RGB9_E5; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case GL_UNSIGNED_INT_10F_11F_11F_REV: 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(ctx->Extensions.EXT_packed_float); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return GL_R11F_G11F_B10F; 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create a temporary texture to hold an image of the given size. 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If width, height are not POT and the driver only handles POT textures, 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * allocate the next larger size of texture that is POT. 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct pipe_resource * 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownalloc_texture(struct st_context *st, GLsizei width, GLsizei height, 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum pipe_format texFormat) 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct pipe_resource *pt; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pt = st_texture_create(st, st->internal_target, texFormat, 0, 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pt; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Make texture containing an image for glDrawPixels image. 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If 'pixels' is NULL, leave the texture image data undefined. 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct pipe_resource * 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmake_texture(struct st_context *st, 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLsizei width, GLsizei height, GLenum format, GLenum type, 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct gl_pixelstore_attrib *unpack, 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const GLvoid *pixels) 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct gl_context *ctx = st->ctx; 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct pipe_context *pipe = st->pipe; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gl_format mformat; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct pipe_resource *pt; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum pipe_format pipeFormat; 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLuint cpp; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GLenum baseFormat, intFormat; 424 425 baseFormat = base_format(format); 426 intFormat = internal_format(ctx, format, type); 427 428 mformat = st_ChooseTextureFormat_renderable(ctx, intFormat, 429 format, type, GL_FALSE); 430 assert(mformat); 431 432 pipeFormat = st_mesa_format_to_pipe_format(mformat); 433 assert(pipeFormat); 434 cpp = util_format_get_blocksize(pipeFormat); 435 436 pixels = _mesa_map_pbo_source(ctx, unpack, pixels); 437 if (!pixels) 438 return NULL; 439 440 /* alloc temporary texture */ 441 pt = alloc_texture(st, width, height, pipeFormat); 442 if (!pt) { 443 _mesa_unmap_pbo_source(ctx, unpack); 444 return NULL; 445 } 446 447 { 448 struct pipe_transfer *transfer; 449 static const GLuint dstImageOffsets = 0; 450 GLboolean success; 451 GLubyte *dest; 452 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; 453 454 /* we'll do pixel transfer in a fragment shader */ 455 ctx->_ImageTransferState = 0x0; 456 457 transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 458 PIPE_TRANSFER_WRITE, 0, 0, 459 width, height); 460 461 /* map texture transfer */ 462 dest = pipe_transfer_map(pipe, transfer); 463 464 465 /* Put image into texture transfer. 466 * Note that the image is actually going to be upside down in 467 * the texture. We deal with that with texcoords. 468 */ 469 success = _mesa_texstore(ctx, 2, /* dims */ 470 baseFormat, /* baseInternalFormat */ 471 mformat, /* gl_format */ 472 dest, /* dest */ 473 0, 0, 0, /* dstX/Y/Zoffset */ 474 transfer->stride, /* dstRowStride, bytes */ 475 &dstImageOffsets, /* dstImageOffsets */ 476 width, height, 1, /* size */ 477 format, type, /* src format/type */ 478 pixels, /* data source */ 479 unpack); 480 481 /* unmap */ 482 pipe_transfer_unmap(pipe, transfer); 483 pipe->transfer_destroy(pipe, transfer); 484 485 assert(success); 486 487 /* restore */ 488 ctx->_ImageTransferState = imageTransferStateSave; 489 } 490 491 _mesa_unmap_pbo_source(ctx, unpack); 492 493 return pt; 494} 495 496 497/** 498 * Draw quad with texcoords and optional color. 499 * Coords are gallium window coords with y=0=top. 500 * \param color may be null 501 * \param invertTex if true, flip texcoords vertically 502 */ 503static void 504draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, 505 GLfloat x1, GLfloat y1, const GLfloat *color, 506 GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) 507{ 508 struct st_context *st = st_context(ctx); 509 struct pipe_context *pipe = st->pipe; 510 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ 511 512 /* setup vertex data */ 513 { 514 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 515 const GLfloat fb_width = (GLfloat) fb->Width; 516 const GLfloat fb_height = (GLfloat) fb->Height; 517 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; 518 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; 519 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; 520 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; 521 const GLfloat sLeft = 0.0f, sRight = maxXcoord; 522 const GLfloat tTop = invertTex ? maxYcoord : 0.0f; 523 const GLfloat tBot = invertTex ? 0.0f : maxYcoord; 524 GLuint i; 525 526 /* upper-left */ 527 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ 528 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ 529 530 /* upper-right */ 531 verts[1][0][0] = clip_x1; 532 verts[1][0][1] = clip_y0; 533 534 /* lower-right */ 535 verts[2][0][0] = clip_x1; 536 verts[2][0][1] = clip_y1; 537 538 /* lower-left */ 539 verts[3][0][0] = clip_x0; 540 verts[3][0][1] = clip_y1; 541 542 verts[0][1][0] = sLeft; /* v[0].attr[1].S */ 543 verts[0][1][1] = tTop; /* v[0].attr[1].T */ 544 verts[1][1][0] = sRight; 545 verts[1][1][1] = tTop; 546 verts[2][1][0] = sRight; 547 verts[2][1][1] = tBot; 548 verts[3][1][0] = sLeft; 549 verts[3][1][1] = tBot; 550 551 /* same for all verts: */ 552 if (color) { 553 for (i = 0; i < 4; i++) { 554 verts[i][0][2] = z; /* v[i].attr[0].z */ 555 verts[i][0][3] = 1.0f; /* v[i].attr[0].w */ 556 verts[i][2][0] = color[0]; /* v[i].attr[2].r */ 557 verts[i][2][1] = color[1]; /* v[i].attr[2].g */ 558 verts[i][2][2] = color[2]; /* v[i].attr[2].b */ 559 verts[i][2][3] = color[3]; /* v[i].attr[2].a */ 560 verts[i][1][2] = 0.0f; /* v[i].attr[1].R */ 561 verts[i][1][3] = 1.0f; /* v[i].attr[1].Q */ 562 } 563 } 564 else { 565 for (i = 0; i < 4; i++) { 566 verts[i][0][2] = z; /*Z*/ 567 verts[i][0][3] = 1.0f; /*W*/ 568 verts[i][1][2] = 0.0f; /*R*/ 569 verts[i][1][3] = 1.0f; /*Q*/ 570 } 571 } 572 } 573 574 { 575 struct pipe_resource *buf; 576 577 /* allocate/load buffer object with vertex data */ 578 buf = pipe_buffer_create(pipe->screen, 579 PIPE_BIND_VERTEX_BUFFER, 580 PIPE_USAGE_STATIC, 581 sizeof(verts)); 582 pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts); 583 584 util_draw_vertex_buffer(pipe, st->cso_context, buf, 0, 585 PIPE_PRIM_QUADS, 586 4, /* verts */ 587 3); /* attribs/vert */ 588 pipe_resource_reference(&buf, NULL); 589 } 590} 591 592 593 594static void 595draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, 596 GLsizei width, GLsizei height, 597 GLfloat zoomX, GLfloat zoomY, 598 struct pipe_sampler_view **sv, 599 int num_sampler_view, 600 void *driver_vp, 601 void *driver_fp, 602 const GLfloat *color, 603 GLboolean invertTex, 604 GLboolean write_depth, GLboolean write_stencil) 605{ 606 struct st_context *st = st_context(ctx); 607 struct pipe_context *pipe = st->pipe; 608 struct cso_context *cso = st->cso_context; 609 GLfloat x0, y0, x1, y1; 610 GLsizei maxSize; 611 boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT; 612 613 /* limit checks */ 614 /* XXX if DrawPixels image is larger than max texture size, break 615 * it up into chunks. 616 */ 617 maxSize = 1 << (pipe->screen->get_param(pipe->screen, 618 PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 619 assert(width <= maxSize); 620 assert(height <= maxSize); 621 622 cso_save_rasterizer(cso); 623 cso_save_viewport(cso); 624 cso_save_samplers(cso); 625 cso_save_fragment_sampler_views(cso); 626 cso_save_fragment_shader(cso); 627 cso_save_vertex_shader(cso); 628 cso_save_vertex_elements(cso); 629 cso_save_vertex_buffers(cso); 630 if (write_stencil) { 631 cso_save_depth_stencil_alpha(cso); 632 cso_save_blend(cso); 633 } 634 635 /* rasterizer state: just scissor */ 636 { 637 struct pipe_rasterizer_state rasterizer; 638 memset(&rasterizer, 0, sizeof(rasterizer)); 639 rasterizer.clamp_fragment_color = ctx->Color._ClampFragmentColor; 640 rasterizer.gl_rasterization_rules = 1; 641 rasterizer.scissor = ctx->Scissor.Enabled; 642 cso_set_rasterizer(cso, &rasterizer); 643 } 644 645 if (write_stencil) { 646 /* Stencil writing bypasses the normal fragment pipeline to 647 * disable color writing and set stencil test to always pass. 648 */ 649 struct pipe_depth_stencil_alpha_state dsa; 650 struct pipe_blend_state blend; 651 652 /* depth/stencil */ 653 memset(&dsa, 0, sizeof(dsa)); 654 dsa.stencil[0].enabled = 1; 655 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 656 dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; 657 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 658 if (write_depth) { 659 /* writing depth+stencil: depth test always passes */ 660 dsa.depth.enabled = 1; 661 dsa.depth.writemask = ctx->Depth.Mask; 662 dsa.depth.func = PIPE_FUNC_ALWAYS; 663 } 664 cso_set_depth_stencil_alpha(cso, &dsa); 665 666 /* blend (colormask) */ 667 memset(&blend, 0, sizeof(blend)); 668 cso_set_blend(cso, &blend); 669 } 670 671 /* fragment shader state: TEX lookup program */ 672 cso_set_fragment_shader_handle(cso, driver_fp); 673 674 /* vertex shader state: position + texcoord pass-through */ 675 cso_set_vertex_shader_handle(cso, driver_vp); 676 677 678 /* texture sampling state: */ 679 { 680 struct pipe_sampler_state sampler; 681 memset(&sampler, 0, sizeof(sampler)); 682 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; 683 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; 684 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; 685 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 686 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 687 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 688 sampler.normalized_coords = normalized; 689 690 cso_single_sampler(cso, 0, &sampler); 691 if (num_sampler_view > 1) { 692 cso_single_sampler(cso, 1, &sampler); 693 } 694 cso_single_sampler_done(cso); 695 } 696 697 /* viewport state: viewport matching window dims */ 698 { 699 const float w = (float) ctx->DrawBuffer->Width; 700 const float h = (float) ctx->DrawBuffer->Height; 701 struct pipe_viewport_state vp; 702 vp.scale[0] = 0.5f * w; 703 vp.scale[1] = -0.5f * h; 704 vp.scale[2] = 0.5f; 705 vp.scale[3] = 1.0f; 706 vp.translate[0] = 0.5f * w; 707 vp.translate[1] = 0.5f * h; 708 vp.translate[2] = 0.5f; 709 vp.translate[3] = 0.0f; 710 cso_set_viewport(cso, &vp); 711 } 712 713 cso_set_vertex_elements(cso, 3, st->velems_util_draw); 714 715 /* texture state: */ 716 cso_set_fragment_sampler_views(cso, num_sampler_view, sv); 717 718 /* Compute Gallium window coords (y=0=top) with pixel zoom. 719 * Recall that these coords are transformed by the current 720 * vertex shader and viewport transformation. 721 */ 722 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { 723 y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY); 724 invertTex = !invertTex; 725 } 726 727 x0 = (GLfloat) x; 728 x1 = x + width * ctx->Pixel.ZoomX; 729 y0 = (GLfloat) y; 730 y1 = y + height * ctx->Pixel.ZoomY; 731 732 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ 733 z = z * 2.0 - 1.0; 734 735 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, 736 normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width, 737 normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height); 738 739 /* restore state */ 740 cso_restore_rasterizer(cso); 741 cso_restore_viewport(cso); 742 cso_restore_samplers(cso); 743 cso_restore_fragment_sampler_views(cso); 744 cso_restore_fragment_shader(cso); 745 cso_restore_vertex_shader(cso); 746 cso_restore_vertex_elements(cso); 747 cso_restore_vertex_buffers(cso); 748 if (write_stencil) { 749 cso_restore_depth_stencil_alpha(cso); 750 cso_restore_blend(cso); 751 } 752} 753 754 755/** 756 * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we 757 * can't use a fragment shader to write stencil values. 758 */ 759static void 760draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, 761 GLsizei width, GLsizei height, GLenum format, GLenum type, 762 const struct gl_pixelstore_attrib *unpack, 763 const GLvoid *pixels) 764{ 765 struct st_context *st = st_context(ctx); 766 struct pipe_context *pipe = st->pipe; 767 struct st_renderbuffer *strb; 768 enum pipe_transfer_usage usage; 769 struct pipe_transfer *pt; 770 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 771 GLint skipPixels; 772 ubyte *stmap; 773 struct gl_pixelstore_attrib clippedUnpack = *unpack; 774 775 if (!zoom) { 776 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 777 &clippedUnpack)) { 778 /* totally clipped */ 779 return; 780 } 781 } 782 783 strb = st_renderbuffer(ctx->DrawBuffer-> 784 Attachment[BUFFER_STENCIL].Renderbuffer); 785 786 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 787 y = ctx->DrawBuffer->Height - y - height; 788 } 789 790 if(format != GL_DEPTH_STENCIL && 791 util_format_get_component_bits(strb->format, 792 UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) 793 usage = PIPE_TRANSFER_READ_WRITE; 794 else 795 usage = PIPE_TRANSFER_WRITE; 796 797 pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 798 usage, x, y, 799 width, height); 800 801 stmap = pipe_transfer_map(pipe, pt); 802 803 pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); 804 assert(pixels); 805 806 /* if width > MAX_WIDTH, have to process image in chunks */ 807 skipPixels = 0; 808 while (skipPixels < width) { 809 const GLint spanX = skipPixels; 810 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 811 GLint row; 812 for (row = 0; row < height; row++) { 813 GLubyte sValues[MAX_WIDTH]; 814 GLuint zValues[MAX_WIDTH]; 815 GLenum destType = GL_UNSIGNED_BYTE; 816 const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, 817 width, height, 818 format, type, 819 row, skipPixels); 820 _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, 821 type, source, &clippedUnpack, 822 ctx->_ImageTransferState); 823 824 if (format == GL_DEPTH_STENCIL) { 825 _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, 826 (1 << 24) - 1, type, source, 827 &clippedUnpack); 828 } 829 830 if (zoom) { 831 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " 832 "zoom not complete"); 833 } 834 835 { 836 GLint spanY; 837 838 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 839 spanY = height - row - 1; 840 } 841 else { 842 spanY = row; 843 } 844 845 /* now pack the stencil (and Z) values in the dest format */ 846 switch (pt->resource->format) { 847 case PIPE_FORMAT_S8_USCALED: 848 { 849 ubyte *dest = stmap + spanY * pt->stride + spanX; 850 assert(usage == PIPE_TRANSFER_WRITE); 851 memcpy(dest, sValues, spanWidth); 852 } 853 break; 854 case PIPE_FORMAT_Z24_UNORM_S8_USCALED: 855 if (format == GL_DEPTH_STENCIL) { 856 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 857 GLint k; 858 assert(usage == PIPE_TRANSFER_WRITE); 859 for (k = 0; k < spanWidth; k++) { 860 dest[k] = zValues[k] | (sValues[k] << 24); 861 } 862 } 863 else { 864 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 865 GLint k; 866 assert(usage == PIPE_TRANSFER_READ_WRITE); 867 for (k = 0; k < spanWidth; k++) { 868 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); 869 } 870 } 871 break; 872 case PIPE_FORMAT_S8_USCALED_Z24_UNORM: 873 if (format == GL_DEPTH_STENCIL) { 874 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 875 GLint k; 876 assert(usage == PIPE_TRANSFER_WRITE); 877 for (k = 0; k < spanWidth; k++) { 878 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); 879 } 880 } 881 else { 882 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 883 GLint k; 884 assert(usage == PIPE_TRANSFER_READ_WRITE); 885 for (k = 0; k < spanWidth; k++) { 886 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); 887 } 888 } 889 break; 890 default: 891 assert(0); 892 } 893 } 894 } 895 skipPixels += spanWidth; 896 } 897 898 _mesa_unmap_pbo_source(ctx, &clippedUnpack); 899 900 /* unmap the stencil buffer */ 901 pipe_transfer_unmap(pipe, pt); 902 pipe->transfer_destroy(pipe, pt); 903} 904 905 906/** 907 * Get fragment program variant for a glDrawPixels or glCopyPixels 908 * command for RGBA data. 909 */ 910static struct st_fp_variant * 911get_color_fp_variant(struct st_context *st) 912{ 913 struct gl_context *ctx = st->ctx; 914 struct st_fp_variant_key key; 915 struct st_fp_variant *fpv; 916 917 memset(&key, 0, sizeof(key)); 918 919 key.st = st; 920 key.drawpixels = 1; 921 key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 || 922 ctx->Pixel.RedScale != 1.0 || 923 ctx->Pixel.GreenBias != 0.0 || 924 ctx->Pixel.GreenScale != 1.0 || 925 ctx->Pixel.BlueBias != 0.0 || 926 ctx->Pixel.BlueScale != 1.0 || 927 ctx->Pixel.AlphaBias != 0.0 || 928 ctx->Pixel.AlphaScale != 1.0); 929 key.pixelMaps = ctx->Pixel.MapColorFlag; 930 931 fpv = st_get_fp_variant(st, st->fp, &key); 932 933 return fpv; 934} 935 936 937/** 938 * Get fragment program variant for a glDrawPixels or glCopyPixels 939 * command for depth/stencil data. 940 */ 941static struct st_fp_variant * 942get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth, 943 GLboolean write_stencil) 944{ 945 struct st_fp_variant_key key; 946 struct st_fp_variant *fpv; 947 948 memset(&key, 0, sizeof(key)); 949 950 key.st = st; 951 key.drawpixels = 1; 952 key.drawpixels_z = write_depth; 953 key.drawpixels_stencil = write_stencil; 954 955 fpv = st_get_fp_variant(st, st->fp, &key); 956 957 return fpv; 958} 959 960 961/** 962 * Called via ctx->Driver.DrawPixels() 963 */ 964static void 965st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, 966 GLsizei width, GLsizei height, 967 GLenum format, GLenum type, 968 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 969{ 970 void *driver_vp, *driver_fp; 971 struct st_context *st = st_context(ctx); 972 const GLfloat *color; 973 struct pipe_context *pipe = st->pipe; 974 GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE; 975 struct pipe_sampler_view *sv[2]; 976 int num_sampler_view = 1; 977 enum pipe_format stencil_format = PIPE_FORMAT_NONE; 978 struct st_fp_variant *fpv; 979 980 if (format == GL_DEPTH_STENCIL) 981 write_stencil = write_depth = GL_TRUE; 982 else if (format == GL_STENCIL_INDEX) 983 write_stencil = GL_TRUE; 984 else if (format == GL_DEPTH_COMPONENT) 985 write_depth = GL_TRUE; 986 987 if (write_stencil) { 988 enum pipe_format tex_format; 989 /* can we write to stencil if not fallback */ 990 if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) 991 goto stencil_fallback; 992 993 tex_format = st_choose_format(st->pipe->screen, base_format(format), 994 PIPE_TEXTURE_2D, 995 0, PIPE_BIND_SAMPLER_VIEW); 996 if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) 997 stencil_format = PIPE_FORMAT_X24S8_USCALED; 998 else if (tex_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) 999 stencil_format = PIPE_FORMAT_S8X24_USCALED; 1000 else 1001 stencil_format = PIPE_FORMAT_S8_USCALED; 1002 if (stencil_format == PIPE_FORMAT_NONE) 1003 goto stencil_fallback; 1004 } 1005 1006 /* Mesa state should be up to date by now */ 1007 assert(ctx->NewState == 0x0); 1008 1009 st_validate_state(st); 1010 1011 /* 1012 * Get vertex/fragment shaders 1013 */ 1014 if (write_depth || write_stencil) { 1015 fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); 1016 1017 driver_fp = fpv->driver_shader; 1018 1019 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 1020 1021 color = ctx->Current.RasterColor; 1022 } 1023 else { 1024 fpv = get_color_fp_variant(st); 1025 1026 driver_fp = fpv->driver_shader; 1027 1028 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 1029 1030 color = NULL; 1031 if (st->pixel_xfer.pixelmap_enabled) { 1032 sv[1] = st->pixel_xfer.pixelmap_sampler_view; 1033 num_sampler_view++; 1034 } 1035 } 1036 1037 /* update fragment program constants */ 1038 st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); 1039 1040 /* draw with textured quad */ 1041 { 1042 struct pipe_resource *pt 1043 = make_texture(st, width, height, format, type, unpack, pixels); 1044 if (pt) { 1045 sv[0] = st_create_texture_sampler_view(st->pipe, pt); 1046 1047 if (sv[0]) { 1048 if (write_stencil) { 1049 sv[1] = st_create_texture_sampler_view_format(st->pipe, pt, 1050 stencil_format); 1051 num_sampler_view++; 1052 } 1053 1054 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], 1055 width, height, 1056 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1057 sv, 1058 num_sampler_view, 1059 driver_vp, 1060 driver_fp, 1061 color, GL_FALSE, write_depth, write_stencil); 1062 pipe_sampler_view_reference(&sv[0], NULL); 1063 if (num_sampler_view > 1) 1064 pipe_sampler_view_reference(&sv[1], NULL); 1065 } 1066 pipe_resource_reference(&pt, NULL); 1067 } 1068 } 1069 return; 1070 1071stencil_fallback: 1072 draw_stencil_pixels(ctx, x, y, width, height, format, type, 1073 unpack, pixels); 1074} 1075 1076 1077 1078/** 1079 * Software fallback for glCopyPixels(GL_STENCIL). 1080 */ 1081static void 1082copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1083 GLsizei width, GLsizei height, 1084 GLint dstx, GLint dsty) 1085{ 1086 struct st_renderbuffer *rbDraw; 1087 struct pipe_context *pipe = st_context(ctx)->pipe; 1088 enum pipe_transfer_usage usage; 1089 struct pipe_transfer *ptDraw; 1090 ubyte *drawMap; 1091 ubyte *buffer; 1092 int i; 1093 1094 buffer = malloc(width * height * sizeof(ubyte)); 1095 if (!buffer) { 1096 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); 1097 return; 1098 } 1099 1100 /* Get the dest renderbuffer. If there's a wrapper, use the 1101 * underlying renderbuffer. 1102 */ 1103 rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); 1104 if (rbDraw->Base.Wrapped) 1105 rbDraw = st_renderbuffer(rbDraw->Base.Wrapped); 1106 1107 /* this will do stencil pixel transfer ops */ 1108 st_read_stencil_pixels(ctx, srcx, srcy, width, height, 1109 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 1110 &ctx->DefaultPacking, buffer); 1111 1112 if (0) { 1113 /* debug code: dump stencil values */ 1114 GLint row, col; 1115 for (row = 0; row < height; row++) { 1116 printf("%3d: ", row); 1117 for (col = 0; col < width; col++) { 1118 printf("%02x ", buffer[col + row * width]); 1119 } 1120 printf("\n"); 1121 } 1122 } 1123 1124 if (util_format_get_component_bits(rbDraw->format, 1125 UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) 1126 usage = PIPE_TRANSFER_READ_WRITE; 1127 else 1128 usage = PIPE_TRANSFER_WRITE; 1129 1130 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1131 dsty = rbDraw->Base.Height - dsty - height; 1132 } 1133 1134 ptDraw = pipe_get_transfer(st_context(ctx)->pipe, 1135 rbDraw->texture, 0, 0, 1136 usage, dstx, dsty, 1137 width, height); 1138 1139 assert(util_format_get_blockwidth(ptDraw->resource->format) == 1); 1140 assert(util_format_get_blockheight(ptDraw->resource->format) == 1); 1141 1142 /* map the stencil buffer */ 1143 drawMap = pipe_transfer_map(pipe, ptDraw); 1144 1145 /* draw */ 1146 /* XXX PixelZoom not handled yet */ 1147 for (i = 0; i < height; i++) { 1148 ubyte *dst; 1149 const ubyte *src; 1150 int y; 1151 1152 y = i; 1153 1154 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1155 y = height - y - 1; 1156 } 1157 1158 dst = drawMap + y * ptDraw->stride; 1159 src = buffer + i * width; 1160 1161 switch (ptDraw->resource->format) { 1162 case PIPE_FORMAT_Z24_UNORM_S8_USCALED: 1163 { 1164 uint *dst4 = (uint *) dst; 1165 int j; 1166 assert(usage == PIPE_TRANSFER_READ_WRITE); 1167 for (j = 0; j < width; j++) { 1168 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); 1169 dst4++; 1170 } 1171 } 1172 break; 1173 case PIPE_FORMAT_S8_USCALED_Z24_UNORM: 1174 { 1175 uint *dst4 = (uint *) dst; 1176 int j; 1177 assert(usage == PIPE_TRANSFER_READ_WRITE); 1178 for (j = 0; j < width; j++) { 1179 *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff); 1180 dst4++; 1181 } 1182 } 1183 break; 1184 case PIPE_FORMAT_S8_USCALED: 1185 assert(usage == PIPE_TRANSFER_WRITE); 1186 memcpy(dst, src, width); 1187 break; 1188 default: 1189 assert(0); 1190 } 1191 } 1192 1193 free(buffer); 1194 1195 /* unmap the stencil buffer */ 1196 pipe_transfer_unmap(pipe, ptDraw); 1197 pipe->transfer_destroy(pipe, ptDraw); 1198} 1199 1200 1201/** Do the src/dest regions overlap? */ 1202static GLboolean 1203regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY, 1204 GLsizei width, GLsizei height) 1205{ 1206 if (srcX + width <= dstX || 1207 dstX + width <= srcX || 1208 srcY + height <= dstY || 1209 dstY + height <= srcY) 1210 return GL_FALSE; 1211 else 1212 return GL_TRUE; 1213} 1214 1215 1216/** 1217 * Try to do a glCopyPixels for simple cases with a blit by calling 1218 * pipe->resource_copy_region(). 1219 * 1220 * We can do this when we're copying color pixels (depth/stencil 1221 * eventually) with no pixel zoom, no pixel transfer ops, no 1222 * per-fragment ops, the src/dest regions don't overlap and the 1223 * src/dest pixel formats are the same. 1224 */ 1225static GLboolean 1226blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1227 GLsizei width, GLsizei height, 1228 GLint dstx, GLint dsty, GLenum type) 1229{ 1230 struct st_context *st = st_context(ctx); 1231 struct pipe_context *pipe = st->pipe; 1232 struct gl_pixelstore_attrib pack, unpack; 1233 GLint readX, readY, readW, readH; 1234 1235 if (type == GL_COLOR && 1236 ctx->Pixel.ZoomX == 1.0 && 1237 ctx->Pixel.ZoomY == 1.0 && 1238 ctx->_ImageTransferState == 0x0 && 1239 !ctx->Color.BlendEnabled && 1240 !ctx->Color.AlphaEnabled && 1241 !ctx->Depth.Test && 1242 !ctx->Fog.Enabled && 1243 !ctx->Stencil.Enabled && 1244 !ctx->FragmentProgram.Enabled && 1245 !ctx->VertexProgram.Enabled && 1246 !ctx->Shader.CurrentFragmentProgram && 1247 st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && 1248 ctx->DrawBuffer->_NumColorDrawBuffers == 1) { 1249 struct st_renderbuffer *rbRead, *rbDraw; 1250 GLint drawX, drawY; 1251 1252 /* 1253 * Clip the read region against the src buffer bounds. 1254 * We'll still allocate a temporary buffer/texture for the original 1255 * src region size but we'll only read the region which is on-screen. 1256 * This may mean that we draw garbage pixels into the dest region, but 1257 * that's expected. 1258 */ 1259 readX = srcx; 1260 readY = srcy; 1261 readW = width; 1262 readH = height; 1263 pack = ctx->DefaultPacking; 1264 if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) 1265 return GL_TRUE; /* all done */ 1266 1267 /* clip against dest buffer bounds and scissor box */ 1268 drawX = dstx + pack.SkipPixels; 1269 drawY = dsty + pack.SkipRows; 1270 unpack = pack; 1271 if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) 1272 return GL_TRUE; /* all done */ 1273 1274 readX = readX - pack.SkipPixels + unpack.SkipPixels; 1275 readY = readY - pack.SkipRows + unpack.SkipRows; 1276 1277 rbRead = st_get_color_read_renderbuffer(ctx); 1278 rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); 1279 1280 if ((rbRead != rbDraw || 1281 !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && 1282 rbRead->Base.Format == rbDraw->Base.Format) { 1283 struct pipe_box srcBox; 1284 1285 /* flip src/dst position if needed */ 1286 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1287 /* both buffers will have the same orientation */ 1288 readY = ctx->ReadBuffer->Height - readY - readH; 1289 drawY = ctx->DrawBuffer->Height - drawY - readH; 1290 } 1291 1292 u_box_2d(readX, readY, readW, readH, &srcBox); 1293 1294 pipe->resource_copy_region(pipe, 1295 rbDraw->texture, 0, drawX, drawY, 0, 1296 rbRead->texture, 0, &srcBox); 1297 return GL_TRUE; 1298 } 1299 } 1300 1301 return GL_FALSE; 1302} 1303 1304 1305static void 1306st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1307 GLsizei width, GLsizei height, 1308 GLint dstx, GLint dsty, GLenum type) 1309{ 1310 struct st_context *st = st_context(ctx); 1311 struct pipe_context *pipe = st->pipe; 1312 struct pipe_screen *screen = pipe->screen; 1313 struct st_renderbuffer *rbRead; 1314 void *driver_vp, *driver_fp; 1315 struct pipe_resource *pt; 1316 struct pipe_sampler_view *sv[2]; 1317 int num_sampler_view = 1; 1318 GLfloat *color; 1319 enum pipe_format srcFormat, texFormat; 1320 GLboolean invertTex = GL_FALSE; 1321 GLint readX, readY, readW, readH; 1322 GLuint sample_count; 1323 struct gl_pixelstore_attrib pack = ctx->DefaultPacking; 1324 struct st_fp_variant *fpv; 1325 1326 st_validate_state(st); 1327 1328 if (type == GL_STENCIL) { 1329 /* can't use texturing to do stencil */ 1330 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); 1331 return; 1332 } 1333 1334 if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) 1335 return; 1336 1337 /* 1338 * The subsequent code implements glCopyPixels by copying the source 1339 * pixels into a temporary texture that's then applied to a textured quad. 1340 * When we draw the textured quad, all the usual per-fragment operations 1341 * are handled. 1342 */ 1343 1344 1345 /* 1346 * Get vertex/fragment shaders 1347 */ 1348 if (type == GL_COLOR) { 1349 rbRead = st_get_color_read_renderbuffer(ctx); 1350 color = NULL; 1351 1352 fpv = get_color_fp_variant(st); 1353 driver_fp = fpv->driver_shader; 1354 1355 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 1356 1357 if (st->pixel_xfer.pixelmap_enabled) { 1358 sv[1] = st->pixel_xfer.pixelmap_sampler_view; 1359 num_sampler_view++; 1360 } 1361 } 1362 else { 1363 assert(type == GL_DEPTH); 1364 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); 1365 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 1366 1367 fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); 1368 driver_fp = fpv->driver_shader; 1369 1370 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 1371 } 1372 1373 /* update fragment program constants */ 1374 st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); 1375 1376 1377 if (rbRead->Base.Wrapped) 1378 rbRead = st_renderbuffer(rbRead->Base.Wrapped); 1379 1380 sample_count = rbRead->texture->nr_samples; 1381 /* I believe this would be legal, presumably would need to do a resolve 1382 for color, and for depth/stencil spec says to just use one of the 1383 depth/stencil samples per pixel? Need some transfer clarifications. */ 1384 assert(sample_count < 2); 1385 1386 srcFormat = rbRead->texture->format; 1387 1388 if (screen->is_format_supported(screen, srcFormat, st->internal_target, 1389 sample_count, 1390 PIPE_BIND_SAMPLER_VIEW)) { 1391 texFormat = srcFormat; 1392 } 1393 else { 1394 /* srcFormat can't be used as a texture format */ 1395 if (type == GL_DEPTH) { 1396 texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, 1397 st->internal_target, sample_count, 1398 PIPE_BIND_DEPTH_STENCIL); 1399 assert(texFormat != PIPE_FORMAT_NONE); 1400 } 1401 else { 1402 /* default color format */ 1403 texFormat = st_choose_format(screen, GL_RGBA, st->internal_target, 1404 sample_count, PIPE_BIND_SAMPLER_VIEW); 1405 assert(texFormat != PIPE_FORMAT_NONE); 1406 } 1407 } 1408 1409 /* Invert src region if needed */ 1410 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1411 srcy = ctx->ReadBuffer->Height - srcy - height; 1412 invertTex = !invertTex; 1413 } 1414 1415 /* Clip the read region against the src buffer bounds. 1416 * We'll still allocate a temporary buffer/texture for the original 1417 * src region size but we'll only read the region which is on-screen. 1418 * This may mean that we draw garbage pixels into the dest region, but 1419 * that's expected. 1420 */ 1421 readX = srcx; 1422 readY = srcy; 1423 readW = width; 1424 readH = height; 1425 _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); 1426 readW = MAX2(0, readW); 1427 readH = MAX2(0, readH); 1428 1429 /* alloc temporary texture */ 1430 pt = alloc_texture(st, width, height, texFormat); 1431 if (!pt) 1432 return; 1433 1434 sv[0] = st_create_texture_sampler_view(st->pipe, pt); 1435 if (!sv[0]) { 1436 pipe_resource_reference(&pt, NULL); 1437 return; 1438 } 1439 1440 /* Make temporary texture which is a copy of the src region. 1441 */ 1442 if (srcFormat == texFormat) { 1443 struct pipe_box src_box; 1444 u_box_2d(readX, readY, readW, readH, &src_box); 1445 /* copy source framebuffer surface into mipmap/texture */ 1446 pipe->resource_copy_region(pipe, 1447 pt, /* dest tex */ 1448 0, 1449 pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ 1450 rbRead->texture, /* src tex */ 1451 0, 1452 &src_box); 1453 1454 } 1455 else { 1456 /* CPU-based fallback/conversion */ 1457 struct pipe_transfer *ptRead = 1458 pipe_get_transfer(st->pipe, rbRead->texture, 1459 0, 0, /* level, layer */ 1460 PIPE_TRANSFER_READ, 1461 readX, readY, readW, readH); 1462 struct pipe_transfer *ptTex; 1463 enum pipe_transfer_usage transfer_usage; 1464 1465 if (ST_DEBUG & DEBUG_FALLBACK) 1466 debug_printf("%s: fallback processing\n", __FUNCTION__); 1467 1468 if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format)) 1469 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1470 else 1471 transfer_usage = PIPE_TRANSFER_WRITE; 1472 1473 ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage, 1474 0, 0, width, height); 1475 1476 /* copy image from ptRead surface to ptTex surface */ 1477 if (type == GL_COLOR) { 1478 /* alternate path using get/put_tile() */ 1479 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); 1480 enum pipe_format readFormat, drawFormat; 1481 readFormat = util_format_linear(rbRead->texture->format); 1482 drawFormat = util_format_linear(pt->format); 1483 pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, 1484 readFormat, buf); 1485 pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1486 readW, readH, drawFormat, buf); 1487 free(buf); 1488 } 1489 else { 1490 /* GL_DEPTH */ 1491 GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); 1492 pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); 1493 pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1494 readW, readH, buf); 1495 free(buf); 1496 } 1497 1498 pipe->transfer_destroy(pipe, ptRead); 1499 pipe->transfer_destroy(pipe, ptTex); 1500 } 1501 1502 /* OK, the texture 'pt' contains the src image/pixels. Now draw a 1503 * textured quad with that texture. 1504 */ 1505 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], 1506 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1507 sv, 1508 num_sampler_view, 1509 driver_vp, 1510 driver_fp, 1511 color, invertTex, GL_FALSE, GL_FALSE); 1512 1513 pipe_resource_reference(&pt, NULL); 1514 pipe_sampler_view_reference(&sv[0], NULL); 1515} 1516 1517 1518 1519void st_init_drawpixels_functions(struct dd_function_table *functions) 1520{ 1521 functions->DrawPixels = st_DrawPixels; 1522 functions->CopyPixels = st_CopyPixels; 1523} 1524 1525 1526void 1527st_destroy_drawpix(struct st_context *st) 1528{ 1529 GLuint i; 1530 1531 for (i = 0; i < Elements(st->drawpix.shaders); i++) { 1532 if (st->drawpix.shaders[i]) 1533 _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); 1534 } 1535 1536 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); 1537 if (st->drawpix.vert_shaders[0]) 1538 ureg_free_tokens(st->drawpix.vert_shaders[0]); 1539 if (st->drawpix.vert_shaders[1]) 1540 ureg_free_tokens(st->drawpix.vert_shaders[1]); 1541} 1542 1543#endif /* FEATURE_drawpix */ 1544