/** * Generate mipmap levels using hardware rendering. * \return TRUE if successful, FALSE if not possible */ static boolean st_render_mipmap(struct st_context *st, GLenum target, struct st_texture_object *stObj, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_sampler_view *psv; const uint face = _mesa_tex_target_to_face(target); #if 0 assert(target != GL_TEXTURE_3D); /* implemented but untested */ #endif /* check if we can render in the texture's format */ /* XXX should probably kill this and always use util_gen_mipmap since this implements a sw fallback as well */ if (!screen->is_format_supported(screen, stObj->pt->format, stObj->pt->target, 0, PIPE_BIND_RENDER_TARGET)) { return FALSE; } psv = st_create_texture_sampler_view(pipe, stObj->pt); util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, PIPE_TEX_FILTER_LINEAR); pipe_sampler_view_reference(&psv, NULL); return TRUE; }
/** * If there's anything in the bitmap cache, draw/flush it now. */ void st_flush_bitmap_cache(struct st_context *st) { if (!st->bitmap.cache->empty) { struct bitmap_cache *cache = st->bitmap.cache; if (st->ctx->DrawBuffer) { struct pipe_context *pipe = st->pipe; struct pipe_sampler_view *sv; assert(cache->xmin <= cache->xmax); /* printf("flush size %d x %d at %d, %d\n", cache->xmax - cache->xmin, cache->ymax - cache->ymin, cache->xpos, cache->ypos); */ /* The texture transfer has been mapped until now. * So unmap and release the texture transfer before drawing. */ if (cache->trans) { if (0) print_cache(cache); pipe_transfer_unmap(pipe, cache->trans); cache->buffer = NULL; pipe->transfer_destroy(pipe, cache->trans); cache->trans = NULL; } sv = st_create_texture_sampler_view(st->pipe, cache->texture); if (sv) { draw_bitmap_quad(st->ctx, cache->xpos, cache->ypos, cache->zpos, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, sv, cache->color); pipe_sampler_view_reference(&sv, NULL); } } /* release/free the texture */ pipe_resource_reference(&cache->texture, NULL); reset_cache(st); } }
/** * Called via ctx->Driver.Bitmap() */ static void st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct st_context *st = st_context(ctx); struct pipe_resource *pt; assert(width > 0); assert(height > 0); st_invalidate_readpix_cache(st); if (!st->bitmap.cache) { init_bitmap_state(st); } /* We only need to validate any non-ST_NEW_CONSTANTS state. The VS we use * for bitmap drawing uses no constants and the FS constants are * explicitly uploaded in the draw_bitmap_quad() function. */ if ((st->dirty | ctx->NewDriverState) & ~ST_NEW_CONSTANTS & ST_PIPELINE_RENDER_STATE_MASK || st->gfx_shaders_may_be_dirty) { st_validate_state(st, ST_PIPELINE_RENDER); } if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap)) return; pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); if (sv) { draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], width, height, sv, ctx->Current.RasterColor); pipe_sampler_view_reference(&sv, NULL); } /* release/free the texture */ pipe_resource_reference(&pt, NULL); } }
/** * Called via ctx->Driver.Bitmap() */ static void st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct st_context *st = st_context(ctx); struct pipe_resource *pt; if (width == 0 || height == 0) return; st_validate_state(st); if (!st->bitmap.vs) { /* create pass-through vertex shader now */ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_COLOR, st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0, 0 }; st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, semantic_names, semantic_indexes, FALSE); } if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap)) return; pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); if (sv) { draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], width, height, sv, st->ctx->Current.RasterColor); pipe_sampler_view_reference(&sv, NULL); } /* release/free the texture */ pipe_resource_reference(&pt, NULL); } }
/** * Upload the pixel transfer color map texture. */ static void update_pixel_transfer(struct st_context *st) { struct gl_context *ctx = st->ctx; if (ctx->Pixel.MapColorFlag) { /* create the colormap/texture now if not already done */ if (!st->pixel_xfer.pixelmap_texture) { st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx); st->pixel_xfer.pixelmap_sampler_view = st_create_texture_sampler_view(st->pipe, st->pixel_xfer.pixelmap_texture); } load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture); } }
/** * Called via ctx->Driver.DrawAtlasBitmap() */ static void st_DrawAtlasBitmaps(struct gl_context *ctx, const struct gl_bitmap_atlas *atlas, GLuint count, const GLubyte *ids) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_object *stObj = st_texture_object(atlas->texObj); struct pipe_sampler_view *sv; /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f; const float *color = ctx->Current.RasterColor; const float clip_x_scale = 2.0f / st->state.framebuffer.width; const float clip_y_scale = 2.0f / st->state.framebuffer.height; const unsigned num_verts = count * 4; const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex); struct st_util_vertex *verts; struct pipe_vertex_buffer vb = {0}; unsigned i; if (!st->bitmap.cache) { init_bitmap_state(st); } st_flush_bitmap_cache(st); st_validate_state(st, ST_PIPELINE_RENDER); st_invalidate_readpix_cache(st); sv = st_create_texture_sampler_view(pipe, stObj->pt); if (!sv) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); return; } setup_render_state(ctx, sv, color, true); vb.stride = sizeof(struct st_util_vertex); u_upload_alloc(st->uploader, 0, num_vert_bytes, 4, &vb.buffer_offset, &vb.buffer, (void **) &verts); /* build quads vertex data */ for (i = 0; i < count; i++) { const GLfloat epsilon = 0.0001F; const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]]; const float xmove = g->xmove, ymove = g->ymove; const float xorig = g->xorig, yorig = g->yorig; const float s0 = g->x, t0 = g->y; const float s1 = s0 + g->w, t1 = t0 + g->h; const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon); const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon); const float x1 = x0 + g->w, y1 = y0 + g->h; const float clip_x0 = x0 * clip_x_scale - 1.0f; const float clip_y0 = y0 * clip_y_scale - 1.0f; const float clip_x1 = x1 * clip_x_scale - 1.0f; const float clip_y1 = y1 * clip_y_scale - 1.0f; /* lower-left corner */ verts->x = clip_x0; verts->y = clip_y0; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s0; verts->t = t0; verts++; /* lower-right corner */ verts->x = clip_x1; verts->y = clip_y0; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s1; verts->t = t0; verts++; /* upper-right corner */ verts->x = clip_x1; verts->y = clip_y1; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s1; verts->t = t1; verts++; /* upper-left corner */ verts->x = clip_x0; verts->y = clip_y1; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s0; verts->t = t1; verts++; /* Update the raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; } u_upload_unmap(st->uploader); cso_set_vertex_buffers(st->cso_context, cso_get_aux_vertex_buffer_slot(st->cso_context), 1, &vb); cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts); restore_render_state(ctx); pipe_resource_reference(&vb.buffer, NULL); pipe_sampler_view_reference(&sv, NULL); /* We uploaded modified constants, need to invalidate them. */ st->dirty |= ST_NEW_FS_CONSTANTS; }
/** * Called via ctx->Driver.DrawPixels() */ static void st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { void *driver_vp, *driver_fp; struct st_context *st = st_context(ctx); const GLfloat *color; struct pipe_context *pipe = st->pipe; GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE; struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; enum pipe_format stencil_format = PIPE_FORMAT_NONE; struct st_fp_variant *fpv; if (format == GL_DEPTH_STENCIL) write_stencil = write_depth = GL_TRUE; else if (format == GL_STENCIL_INDEX) write_stencil = GL_TRUE; else if (format == GL_DEPTH_COMPONENT) write_depth = GL_TRUE; if (write_stencil) { enum pipe_format tex_format; /* can we write to stencil if not fallback */ if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) goto stencil_fallback; tex_format = st_choose_format(st->pipe->screen, base_format(format), GL_NONE, GL_NONE, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW); if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) stencil_format = PIPE_FORMAT_X24S8_USCALED; else if (tex_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) stencil_format = PIPE_FORMAT_S8X24_USCALED; else stencil_format = PIPE_FORMAT_S8_USCALED; if (stencil_format == PIPE_FORMAT_NONE) goto stencil_fallback; } /* Mesa state should be up to date by now */ assert(ctx->NewState == 0x0); st_validate_state(st); /* * Get vertex/fragment shaders */ if (write_depth || write_stencil) { fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); color = ctx->Current.RasterColor; } else { fpv = get_color_fp_variant(st); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); color = NULL; if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; } } /* update fragment program constants */ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); /* draw with textured quad */ { struct pipe_resource *pt = make_texture(st, width, height, format, type, unpack, pixels); if (pt) { sv[0] = st_create_texture_sampler_view(st->pipe, pt); if (sv[0]) { if (write_stencil) { sv[1] = st_create_texture_sampler_view_format(st->pipe, pt, stencil_format); num_sampler_view++; } draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, sv, num_sampler_view, driver_vp, driver_fp, color, GL_FALSE, write_depth, write_stencil); pipe_sampler_view_reference(&sv[0], NULL); if (num_sampler_view > 1) pipe_sampler_view_reference(&sv[1], NULL); } pipe_resource_reference(&pt, NULL); } } return; stencil_fallback: draw_stencil_pixels(ctx, x, y, width, height, format, type, unpack, pixels); }
static void st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; void *driver_vp, *driver_fp; struct pipe_resource *pt; struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; GLfloat *color; enum pipe_format srcFormat, texFormat; GLboolean invertTex = GL_FALSE; GLint readX, readY, readW, readH; GLuint sample_count; struct gl_pixelstore_attrib pack = ctx->DefaultPacking; struct st_fp_variant *fpv; st_validate_state(st); if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); return; } if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) return; /* * The subsequent code implements glCopyPixels by copying the source * pixels into a temporary texture that's then applied to a textured quad. * When we draw the textured quad, all the usual per-fragment operations * are handled. */ /* * Get vertex/fragment shaders */ if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; fpv = get_color_fp_variant(st); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; } } else { assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); } /* update fragment program constants */ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); if (rbRead->Base.Wrapped) rbRead = st_renderbuffer(rbRead->Base.Wrapped); sample_count = rbRead->texture->nr_samples; /* I believe this would be legal, presumably would need to do a resolve for color, and for depth/stencil spec says to just use one of the depth/stencil samples per pixel? Need some transfer clarifications. */ assert(sample_count < 2); srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, st->internal_target, sample_count, PIPE_BIND_SAMPLER_VIEW)) { texFormat = srcFormat; } else { /* srcFormat can't be used as a texture format */ if (type == GL_DEPTH) { texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, GL_NONE, GL_NONE, st->internal_target, sample_count, PIPE_BIND_DEPTH_STENCIL); assert(texFormat != PIPE_FORMAT_NONE); } else { /* default color format */ texFormat = st_choose_format(screen, GL_RGBA, GL_NONE, GL_NONE, st->internal_target, sample_count, PIPE_BIND_SAMPLER_VIEW); assert(texFormat != PIPE_FORMAT_NONE); } } /* Invert src region if needed */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcy = ctx->ReadBuffer->Height - srcy - height; invertTex = !invertTex; } /* Clip the read region against the src buffer bounds. * We'll still allocate a temporary buffer/texture for the original * src region size but we'll only read the region which is on-screen. * This may mean that we draw garbage pixels into the dest region, but * that's expected. */ readX = srcx; readY = srcy; readW = width; readH = height; _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); readW = MAX2(0, readW); readH = MAX2(0, readH); /* alloc temporary texture */ pt = alloc_texture(st, width, height, texFormat); if (!pt) return; sv[0] = st_create_texture_sampler_view(st->pipe, pt); if (!sv[0]) { pipe_resource_reference(&pt, NULL); return; } /* Make temporary texture which is a copy of the src region. */ if (srcFormat == texFormat) { struct pipe_box src_box; u_box_2d(readX, readY, readW, readH, &src_box); /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ 0, /* dest lvl */ pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ rbRead->texture, /* src tex */ rbRead->rtt_level, /* src lvl */ &src_box); } else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = pipe_get_transfer(st->pipe, rbRead->texture, rbRead->rtt_level, rbRead->rtt_face + rbRead->rtt_slice, PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage, 0, 0, width, height); /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); enum pipe_format readFormat, drawFormat; readFormat = util_format_linear(rbRead->texture->format); drawFormat = util_format_linear(pt->format); pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, readFormat, buf); pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, drawFormat, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, buf); free(buf); } pipe->transfer_destroy(pipe, ptRead); pipe->transfer_destroy(pipe, ptTex); } /* OK, the texture 'pt' contains the src image/pixels. Now draw a * textured quad with that texture. */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, sv, num_sampler_view, driver_vp, driver_fp, color, invertTex, GL_FALSE, GL_FALSE); pipe_resource_reference(&pt, NULL); pipe_sampler_view_reference(&sv[0], NULL); }
/** * Returns a fragment program which implements the current pixel transfer ops. */ static struct gl_fragment_program * get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key) { struct st_context *st = st_context(ctx); struct prog_instruction inst[MAX_INST]; struct gl_program_parameter_list *params; struct gl_fragment_program *fp; GLuint ic = 0; const GLuint colorTemp = 0; fp = (struct gl_fragment_program *) ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); if (!fp) return NULL; params = _mesa_new_parameter_list(); /* * Get initial pixel color from the texture. * TEX colorTemp, fragment.texcoord[0], texture[0], 2D; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_TEX; inst[ic].DstReg.File = PROGRAM_TEMPORARY; inst[ic].DstReg.Index = colorTemp; inst[ic].SrcReg[0].File = PROGRAM_INPUT; inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; inst[ic].TexSrcUnit = 0; inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; fp->Base.InputsRead = BITFIELD64_BIT(FRAG_ATTRIB_TEX0); fp->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ if (key->scaleAndBias) { static const gl_state_index scale_state[STATE_LENGTH] = { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 }; static const gl_state_index bias_state[STATE_LENGTH] = { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 }; GLint scale_p, bias_p; scale_p = _mesa_add_state_reference(params, scale_state); bias_p = _mesa_add_state_reference(params, bias_state); /* MAD colorTemp, colorTemp, scale, bias; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_MAD; inst[ic].DstReg.File = PROGRAM_TEMPORARY; inst[ic].DstReg.Index = colorTemp; inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; inst[ic].SrcReg[0].Index = colorTemp; inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR; inst[ic].SrcReg[1].Index = scale_p; inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR; inst[ic].SrcReg[2].Index = bias_p; ic++; } if (key->pixelMaps) { const GLuint temp = 1; /* create the colormap/texture now if not already done */ if (!st->pixel_xfer.pixelmap_texture) { st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx); st->pixel_xfer.pixelmap_sampler_view = st_create_texture_sampler_view(st->pipe, st->pixel_xfer.pixelmap_texture); } /* with a little effort, we can do four pixel map look-ups with * two TEX instructions: */ /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_TEX; inst[ic].DstReg.File = PROGRAM_TEMPORARY; inst[ic].DstReg.Index = temp; inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; inst[ic].SrcReg[0].Index = colorTemp; inst[ic].TexSrcUnit = 1; inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_TEX; inst[ic].DstReg.File = PROGRAM_TEMPORARY; inst[ic].DstReg.Index = temp; inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; inst[ic].SrcReg[0].Index = colorTemp; inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W); inst[ic].TexSrcUnit = 1; inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; /* MOV colorTemp, temp; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_MOV; inst[ic].DstReg.File = PROGRAM_TEMPORARY; inst[ic].DstReg.Index = colorTemp; inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; inst[ic].SrcReg[0].Index = temp; ic++; fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */ } /* Modify last instruction's dst reg to write to result.color */ { struct prog_instruction *last = &inst[ic - 1]; last->DstReg.File = PROGRAM_OUTPUT; last->DstReg.Index = FRAG_RESULT_COLOR; } /* END; */ _mesa_init_instructions(inst + ic, 1); inst[ic].Opcode = OPCODE_END; ic++; assert(ic <= MAX_INST); fp->Base.Instructions = _mesa_alloc_instructions(ic); if (!fp->Base.Instructions) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating pixel transfer program"); _mesa_free_parameter_list(params); return NULL; } _mesa_copy_instructions(fp->Base.Instructions, inst, ic); fp->Base.NumInstructions = ic; fp->Base.Parameters = params; #if 0 printf("========= pixel transfer prog\n"); _mesa_print_program(&fp->Base); _mesa_print_parameter_list(fp->Base.Parameters); #endif return fp; }