Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1

This commit is contained in:
Ben Skeggs 2008-03-19 22:51:17 +11:00
commit 62767cf2dd
55 changed files with 4319 additions and 592 deletions

View file

@ -51,6 +51,7 @@ SOURCES = \
manytex.c \
minmag.c \
mipmap_limits.c \
mipmap_view.c \
multipal.c \
no_s3tc.c \
packedpixels.c \
@ -158,6 +159,14 @@ invert: invert.o readtex.o
invert.o: invert.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
mipmap_view: mipmap_view.o readtex.o
$(CC) $(CFLAGS) mipmap_view.o readtex.o $(LIBS) -o $@
mipmap_view.o: mipmap_view.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
readtex.o: readtex.c
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@

241
progs/tests/mipmap_view.c Normal file
View file

@ -0,0 +1,241 @@
/*
* Test mipmap generation and lod bias.
*
* Brian Paul
* 17 March 2008
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include "readtex.h"
#define TEXTURE_FILE "../images/arch.rgb"
static int TexWidth = 256, TexHeight = 256;
static int WinWidth = 1044, WinHeight = 900;
static GLfloat Bias = 0.0;
static GLboolean ScaleQuads = GL_FALSE;
static void
PrintString(const char *s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
s++;
}
}
static void
Display(void)
{
int x, y, bias;
char str[100];
int texWidth = TexWidth, texHeight = TexHeight;
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WinWidth, 0, WinHeight, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1,1,1);
y = WinHeight - 300;
x = 4;
for (bias = -1; bias < 11; bias++) {
glRasterPos2f(x, y + TexHeight + 5);
sprintf(str, "Texture LOD Bias = %d", bias);
PrintString(str);
glPushMatrix();
glTranslatef(x, y, 0);
glEnable(GL_TEXTURE_2D);
if (ScaleQuads) {
if (bias > 0) {
texWidth = TexWidth >> bias;
texHeight = TexHeight >> bias;
if (texWidth < 1)
texWidth = 1;
if (texHeight < 1)
texHeight = 1;
}
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.0);
}
else {
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias);
}
glBegin(GL_POLYGON);
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(1, 0); glVertex2f(texWidth, 0);
glTexCoord2f(1, 1); glVertex2f(texWidth, texHeight);
glTexCoord2f(0, 1); glVertex2f(0, texHeight);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
x += TexWidth + 4;
if (x >= WinWidth) {
x = 4;
y -= 300;
}
}
glutSwapBuffers();
}
static void
Reshape(int width, int height)
{
WinWidth = width;
WinHeight = height;
glViewport(0, 0, width, height);
}
static void
Key(unsigned char key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case 'b':
Bias -= 10;
break;
case 'B':
Bias += 10;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
Bias = 100.0 * (key - '0');
break;
case 's':
ScaleQuads = !ScaleQuads;
break;
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
Init(void)
{
GLfloat maxBias;
if (!glutExtensionSupported("GL_EXT_texture_lod_bias")) {
printf("Sorry, GL_EXT_texture_lod_bias not supported by this renderer.\n");
exit(1);
}
if (!glutExtensionSupported("GL_SGIS_generate_mipmap")) {
printf("Sorry, GL_SGIS_generate_mipmap not supported by this renderer.\n");
exit(1);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (1) {
/* test auto mipmap generation */
GLint width, height, i;
GLenum format;
GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format);
if (!image) {
printf("Error: could not load texture image %s\n", TEXTURE_FILE);
exit(1);
}
/* resize to TexWidth x TexHeight */
if (width != TexWidth || height != TexHeight) {
GLubyte *newImage = malloc(TexWidth * TexHeight * 4);
gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image,
TexWidth, TexHeight, GL_UNSIGNED_BYTE, newImage);
free(image);
image = newImage;
}
printf("Using GL_SGIS_generate_mipmap\n");
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, format, TexWidth, TexHeight, 0,
format, GL_UNSIGNED_BYTE, image);
free(image);
/* make sure mipmap was really generated correctly */
width = TexWidth;
height = TexHeight;
for (i = 0; i < 9; i++) {
GLint w, h;
glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
printf("Level %d size: %d x %d\n", i, w, h);
assert(w == width);
assert(h == height);
width /= 2;
height /= 2;
}
}
else {
if (LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
printf("Using gluBuildMipmaps()\n");
}
else {
printf("Error: could not load texture image %s\n", TEXTURE_FILE);
exit(1);
}
}
/* mipmapping required for this extension */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &maxBias);
printf("GL_RENDERER: %s\n", (char*) glGetString(GL_RENDERER));
printf("LOD bias range: [%g, %g]\n", -maxBias, maxBias);
printf("Press 's' to toggle quad scaling\n");
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(WinWidth, WinHeight);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutDisplayFunc(Display);
Init();
glutMainLoop();
return 0;
}

View file

@ -149,6 +149,12 @@ void cso_set_blend(struct cso_context *ctx,
}
}
void cso_unset_blend(struct cso_context *ctx)
{
ctx->blend = NULL;
}
void cso_single_sampler(struct cso_context *ctx,
unsigned idx,
const struct pipe_sampler_state *templ)
@ -220,6 +226,15 @@ void cso_set_samplers( struct cso_context *ctx,
cso_single_sampler_done( ctx );
}
void cso_unset_samplers( struct cso_context *ctx )
{
uint i;
for (i = 0; i < ctx->nr_samplers; i++)
ctx->samplers[i] = NULL;
}
void cso_set_depth_stencil_alpha(struct cso_context *ctx,
const struct pipe_depth_stencil_alpha_state *templ)
{
@ -252,6 +267,11 @@ void cso_set_depth_stencil_alpha(struct cso_context *ctx,
}
}
void cso_unset_depth_stencil_alpha(struct cso_context *ctx)
{
ctx->depth_stencil = NULL;
}
void cso_set_rasterizer(struct cso_context *ctx,
@ -285,7 +305,10 @@ void cso_set_rasterizer(struct cso_context *ctx,
}
}
void cso_unset_rasterizer(struct cso_context *ctx)
{
ctx->rasterizer = NULL;
}
@ -320,6 +343,12 @@ void cso_set_fragment_shader(struct cso_context *ctx,
}
}
void cso_unset_fragment_shader(struct cso_context *ctx)
{
ctx->fragment_shader = NULL;
}
void cso_set_vertex_shader(struct cso_context *ctx,
const struct pipe_shader_state *templ)
{
@ -350,3 +379,8 @@ void cso_set_vertex_shader(struct cso_context *ctx,
ctx->pipe->bind_vs_state(ctx->pipe, handle);
}
}
void cso_unset_vertex_shader(struct cso_context *ctx)
{
ctx->vertex_shader = NULL;
}

View file

@ -44,16 +44,25 @@ struct cso_context *cso_create_context( struct pipe_context *pipe );
void cso_set_blend( struct cso_context *cso,
const struct pipe_blend_state *blend );
void cso_unset_blend(struct cso_context *cso);
void cso_set_depth_stencil_alpha( struct cso_context *cso,
const struct pipe_depth_stencil_alpha_state *dsa );
void cso_unset_depth_stencil_alpha( struct cso_context *cso );
void cso_set_rasterizer( struct cso_context *cso,
const struct pipe_rasterizer_state *rasterizer );
void cso_unset_rasterizer( struct cso_context *cso );
void cso_set_samplers( struct cso_context *cso,
unsigned count,
const struct pipe_sampler_state **states );
void cso_unset_samplers( struct cso_context *cso );
/* Alternate interface to support state trackers that like to modify
* samplers one at a time:
*/
@ -72,9 +81,13 @@ void cso_single_sampler_done( struct cso_context *cso );
void cso_set_fragment_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
void cso_unset_fragment_shader( struct cso_context *cso );
void cso_set_vertex_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
void cso_unset_vertex_shader( struct cso_context *cso );
void cso_destroy_context( struct cso_context *cso );

View file

@ -85,14 +85,52 @@ fetch_store_general( struct draw_context *draw,
const unsigned *pitch = draw->vertex_fetch.pitch;
const ubyte **src = draw->vertex_fetch.src_ptr;
for (i = start; i < count; i++) {
for (i = start; i < start + count; i++) {
for (j = 0; j < nr_attrs; j++) {
/* vinfo->src_index is the output of the vertex shader
* matching this hw-vertex component.
*
* In passthrough, we require a 1:1 mapping between vertex
* shader outputs and inputs, which in turn correspond to
* vertex elements in the state. So, this is the vertex
* element we're interested in...
*/
const uint jj = vinfo->src_index[j];
const enum pipe_format srcFormat = draw->vertex_element[jj].src_format;
const ubyte *from = src[jj] + i * pitch[jj];
float attrib[4];
/* Except... When we're not. Two cases EMIT_HEADER &
* EMIT_1F_PSIZE don't consume an input. Should have some
* method for indicating this, or change the logic here
* somewhat so it doesn't matter.
*
* Just hack this up now, do something better about it later.
*/
if (vinfo->emit[j] == EMIT_HEADER) {
memset(out, 0, sizeof(struct vertex_header));
out += sizeof(struct vertex_header) / 4;
continue;
}
else if (vinfo->emit[j] == EMIT_1F_PSIZE) {
out[0] = 1.0; /* xxx */
out += 1;
continue;
}
/* The normal fetch/emit code:
*/
switch (srcFormat) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *ub = (ubyte *) from;
attrib[0] = UBYTE_TO_FLOAT(ub[0]);
attrib[1] = UBYTE_TO_FLOAT(ub[1]);
attrib[2] = UBYTE_TO_FLOAT(ub[2]);
attrib[3] = UBYTE_TO_FLOAT(ub[3]);
}
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *f = (float *) from;
@ -130,14 +168,21 @@ fetch_store_general( struct draw_context *draw,
}
break;
default:
abort();
assert(0);
}
/* XXX this will probably only work for softpipe */
debug_printf("attrib %d: %f %f %f %f\n", j,
attrib[0], attrib[1], attrib[2], attrib[3]);
switch (vinfo->emit[j]) {
case EMIT_HEADER:
memset(out, 0, sizeof(struct vertex_header));
out += sizeof(struct vertex_header) / 4;
case EMIT_1F:
out[0] = attrib[0];
out += 1;
break;
case EMIT_2F:
out[0] = attrib[0];
out[1] = attrib[1];
out += 2;
break;
case EMIT_4F:
out[0] = attrib[0];
@ -147,64 +192,15 @@ fetch_store_general( struct draw_context *draw,
out += 4;
break;
default:
abort();
assert(0);
}
}
debug_printf("\n");
}
}
/* Example of a fetch/emit passthrough shader which could be
* generated when bypass_clipping is enabled on a passthrough vertex
* shader.
*/
static void fetch_xyz_rgb_st( struct draw_context *draw,
float *out,
unsigned start,
unsigned count )
{
const unsigned *pitch = draw->vertex_fetch.pitch;
const ubyte **src = draw->vertex_fetch.src_ptr;
unsigned i;
const ubyte *xyzw = src[0] + start * pitch[0];
const ubyte *rgba = src[1] + start * pitch[1];
const ubyte *st = src[2] + start * pitch[2];
/* loop over vertex attributes (vertex shader inputs)
*/
for (i = 0; i < count; i++) {
{
const float *in = (const float *)xyzw; xyzw += pitch[0];
/* decode input, encode output. Assume both are float[4] */
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = in[3];
}
{
const float *in = (const float *)rgba; rgba += pitch[1];
/* decode input, encode output. Assume both are float[4] */
out[4] = in[0];
out[5] = in[1];
out[6] = in[2];
out[7] = in[3];
}
{
const float *in = (const float *)st; st += pitch[2];
/* decode input, encode output. Assume both are float[2] */
out[8] = in[0];
out[9] = in[1];
}
out += 10;
}
}
static boolean update_shader( struct draw_context *draw )
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
@ -229,70 +225,166 @@ static boolean update_shader( struct draw_context *draw )
draw->pt.hw_vertex_size = vinfo->size * 4;
/* Just trying to figure out how this would work:
*/
if (draw->rasterizer->bypass_vs ||
(nr_attrs == 3 && 0 /* some other tests */))
{
#if 0
draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st;
#else
draw->vertex_fetch.pt_fetch = fetch_store_general;
#endif
/*assert(vinfo->size == 10);*/
draw->vertex_fetch.pt_fetch = fetch_store_general;
return TRUE;
}
static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
{
switch (prim) {
case PIPE_PRIM_POINTS:
*first = 1;
*incr = 1;
return TRUE;
case PIPE_PRIM_LINES:
*first = 2;
*incr = 2;
return TRUE;
case PIPE_PRIM_LINE_STRIP:
*first = 2;
*incr = 1;
return TRUE;
case PIPE_PRIM_TRIANGLES:
*first = 3;
*incr = 3;
return TRUE;
case PIPE_PRIM_TRIANGLE_STRIP:
*first = 3;
*incr = 1;
return TRUE;
case PIPE_PRIM_QUADS:
*first = 4;
*incr = 4;
return TRUE;
case PIPE_PRIM_QUAD_STRIP:
*first = 4;
*incr = 2;
return TRUE;
default:
*first = 0;
*incr = 1; /* set to one so that count % incr works */
return FALSE;
}
return FALSE;
}
static boolean set_prim( struct draw_context *draw,
unsigned prim )
unsigned prim,
unsigned count )
{
assert(!draw->user.elts);
draw->pt.prim = prim;
switch (prim) {
case PIPE_PRIM_LINE_LOOP:
if (count > 1024)
return FALSE;
return draw->render->set_primitive( draw->render, PIPE_PRIM_LINE_STRIP );
case PIPE_PRIM_TRIANGLE_FAN:
case PIPE_PRIM_POLYGON:
if (count > 1024)
return FALSE;
return draw->render->set_primitive( draw->render, prim );
case PIPE_PRIM_QUADS:
case PIPE_PRIM_QUAD_STRIP:
return FALSE;
return draw->render->set_primitive( draw->render, PIPE_PRIM_TRIANGLES );
default:
draw->render->set_primitive( draw->render, prim );
return TRUE;
return draw->render->set_primitive( draw->render, prim );
break;
}
return TRUE;
}
boolean
draw_passthrough_arrays(struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count)
#define INDEX(i) (start + (i))
static void pt_draw_arrays( struct draw_context *draw,
unsigned start,
unsigned length )
{
float *hw_verts;
ushort *tmp = NULL;
unsigned i, j;
if (draw_need_pipeline(draw))
return FALSE;
switch (draw->pt.prim) {
case PIPE_PRIM_LINE_LOOP:
tmp = MALLOC( sizeof(ushort) * (length + 1) );
if (!set_prim(draw, prim))
return FALSE;
for (i = 0; i < length; i++)
tmp[i] = INDEX(i);
tmp[length] = 0;
if (!update_shader(draw))
return FALSE;
draw->render->draw( draw->render,
tmp,
length+1 );
break;
hw_verts = draw->render->allocate_vertices( draw->render,
draw->pt.hw_vertex_size,
count );
case PIPE_PRIM_QUAD_STRIP:
tmp = MALLOC( sizeof(ushort) * (length / 2 * 6) );
for (j = i = 0; i + 3 < length; i += 2, j += 6) {
tmp[j+0] = INDEX(i+0);
tmp[j+1] = INDEX(i+1);
tmp[j+2] = INDEX(i+3);
tmp[j+3] = INDEX(i+2);
tmp[j+4] = INDEX(i+0);
tmp[j+5] = INDEX(i+3);
}
if (j)
draw->render->draw( draw->render, tmp, j );
break;
case PIPE_PRIM_QUADS:
tmp = MALLOC( sizeof(int) * (length / 4 * 6) );
for (j = i = 0; i + 3 < length; i += 4, j += 6) {
tmp[j+0] = INDEX(i+0);
tmp[j+1] = INDEX(i+1);
tmp[j+2] = INDEX(i+3);
tmp[j+3] = INDEX(i+1);
tmp[j+4] = INDEX(i+2);
tmp[j+5] = INDEX(i+3);
}
if (j)
draw->render->draw( draw->render, tmp, j );
break;
default:
draw->render->draw_arrays( draw->render,
start,
length );
break;
}
if (tmp)
FREE(tmp);
}
static boolean do_draw( struct draw_context *draw,
unsigned start, unsigned count )
{
float *hw_verts =
draw->render->allocate_vertices( draw->render,
(ushort)draw->pt.hw_vertex_size,
(ushort)count );
if (!hw_verts)
return FALSE;
/* Single routine to fetch vertices, run shader and emit HW verts.
* Clipping and viewport transformation are done on hardware.
/* Single routine to fetch vertices and emit HW verts.
*/
draw->vertex_fetch.pt_fetch( draw,
hw_verts,
@ -301,9 +393,9 @@ draw_passthrough_arrays(struct draw_context *draw,
/* Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render,
start,
count );
pt_draw_arrays( draw,
0,
count );
draw->render->release_vertices( draw->render,
@ -314,3 +406,68 @@ draw_passthrough_arrays(struct draw_context *draw,
return TRUE;
}
boolean
draw_passthrough_arrays(struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count)
{
unsigned i = 0;
unsigned first, incr;
//debug_printf("%s prim %d start %d count %d\n", __FUNCTION__, prim, start, count);
split_prim_inplace(prim, &first, &incr);
count -= (count - first) % incr;
debug_printf("%s %d %d %d\n", __FUNCTION__, prim, start, count);
if (draw_need_pipeline(draw))
return FALSE;
debug_printf("%s AAA\n", __FUNCTION__);
if (!set_prim(draw, prim, count))
return FALSE;
/* XXX: need a single value that reflects the most recent call to
* driver->set_primitive:
*/
draw->pt.prim = prim;
debug_printf("%s BBB\n", __FUNCTION__);
if (!update_shader(draw))
return FALSE;
debug_printf("%s CCC\n", __FUNCTION__);
/* Chop this up into bite-sized pieces that a driver should be able
* to devour -- problem is we don't have a quick way to query the
* driver on the maximum size for this chunk in the current state.
*/
while (i + first <= count) {
int nr = MIN2( count - i, 1024 );
/* snap to prim boundary
*/
nr -= (nr - first) % incr;
if (!do_draw( draw, start + i, nr )) {
assert(0);
return FALSE;
}
/* increment allowing for repeated vertices
*/
i += nr - (first - incr);
}
debug_printf("%s DONE\n", __FUNCTION__);
return TRUE;
}

View file

@ -169,11 +169,12 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
flushing = TRUE;
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
if (draw->vs.queue_nr)
if (draw->vs.queue_nr) {
if (draw->rasterizer->bypass_vs)
fetch_and_store(draw);
else
(*draw->shader_queue_flush)(draw);
}
if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
if (draw->pq.queue_nr)

View file

@ -74,9 +74,11 @@ struct vbuf_render {
/**
* Notify the renderer of the current primitive when it changes.
* Prim is restricted to TRIANGLES, LINES and POINTS.
* Must succeed for TRIANGLES, LINES and POINTS. Other prims at
* the discretion of the driver, for the benefit of the passthrough
* path.
*/
void (*set_primitive)( struct vbuf_render *, unsigned prim );
boolean (*set_primitive)( struct vbuf_render *, unsigned prim );
/**
* DrawElements, note indices are ushort:

View file

@ -316,7 +316,9 @@ void spe_init_func(struct spe_function *p, unsigned code_size)
void spe_release_func(struct spe_function *p)
{
align_free(p->store);
if (p->store != NULL) {
align_free(p->store);
}
p->store = NULL;
p->csr = NULL;
}
@ -326,8 +328,8 @@ int spe_allocate_available_register(struct spe_function *p)
{
unsigned i;
for (i = 0; i < 128; i++) {
const uint64_t mask = (1ULL << (i % 128));
const unsigned idx = i / 128;
const uint64_t mask = (1ULL << (i % 64));
const unsigned idx = i / 64;
if ((p->regs[idx] & mask) != 0) {
p->regs[idx] &= ~mask;
@ -341,8 +343,8 @@ int spe_allocate_available_register(struct spe_function *p)
int spe_allocate_register(struct spe_function *p, int reg)
{
const unsigned idx = reg / 128;
const unsigned bit = reg % 128;
const unsigned idx = reg / 64;
const unsigned bit = reg % 64;
assert((p->regs[idx] & (1ULL << bit)) != 0);
@ -353,8 +355,8 @@ int spe_allocate_register(struct spe_function *p, int reg)
void spe_release_register(struct spe_function *p, int reg)
{
const unsigned idx = reg / 128;
const unsigned bit = reg % 128;
const unsigned idx = reg / 64;
const unsigned bit = reg % 64;
assert((p->regs[idx] & (1ULL << bit)) == 0);

View file

@ -7,9 +7,13 @@ C_SOURCES = \
p_debug.c \
p_tile.c \
p_util.c \
u_blit.c \
u_draw_quad.c \
u_gen_mipmap.c \
u_handle_table.c \
u_hash_table.c \
u_mm.c \
u_simple_shaders.c \
u_snprintf.c
include ../../Makefile.template

View file

@ -6,9 +6,13 @@ util = env.ConvenienceLibrary(
'p_debug.c',
'p_tile.c',
'p_util.c',
'u_blit.c',
'u_draw_quad.c',
'u_gen_mipmap.c',
'u_handle_table.c',
'u_hash_table.c',
'u_mm.c',
'u_simple_shaders.c',
'u_snprintf.c',
])

View file

@ -0,0 +1,276 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* @file
* Copy/blit pixel rect between surfaces
*
* @author Brian Paul
*/
#include "pipe/p_context.h"
#include "pipe/p_debug.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_draw_quad.h"
#include "util/u_blit.h"
#include "util/u_simple_shaders.h"
struct blit_state
{
struct pipe_context *pipe;
void *blend;
void *depthstencil;
void *rasterizer;
void *samplers[2]; /* one for linear, one for nearest sampling */
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
struct pipe_sampler_state *fs;
};
/**
* Create state object for blit.
* Intended to be created once and re-used for many blit() calls.
*/
struct blit_state *
util_create_blit(struct pipe_context *pipe)
{
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state depthstencil;
struct pipe_rasterizer_state rasterizer;
struct blit_state *ctx;
struct pipe_sampler_state sampler;
ctx = CALLOC_STRUCT(blit_state);
if (!ctx)
return NULL;
ctx->pipe = pipe;
/* we don't use blending, but need to set valid values */
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask = PIPE_MASK_RGBA;
ctx->blend = pipe->create_blend_state(pipe, &blend);
/* depth/stencil/alpha */
memset(&depthstencil, 0, sizeof(depthstencil));
ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
/* rasterizer */
memset(&rasterizer, 0, sizeof(rasterizer));
rasterizer.front_winding = PIPE_WINDING_CW;
rasterizer.cull_mode = PIPE_WINDING_NONE;
rasterizer.bypass_clipping = 1; /* bypasses viewport too */
/*rasterizer.bypass_vs = 1;*/
ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
/* samplers */
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
sampler.normalized_coords = 1;
ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler);
sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler);
#if 0
/* viewport */
ctx->viewport.scale[0] = 1.0;
ctx->viewport.scale[1] = 1.0;
ctx->viewport.scale[2] = 1.0;
ctx->viewport.scale[3] = 1.0;
ctx->viewport.translate[0] = 0.0;
ctx->viewport.translate[1] = 0.0;
ctx->viewport.translate[2] = 0.0;
ctx->viewport.translate[3] = 0.0;
#endif
/* vertex shader */
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0 };
ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
semantic_indexes);
}
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe);
return ctx;
}
/**
* Destroy a blit context
*/
void
util_destroy_blit(struct blit_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
pipe->delete_blend_state(pipe, ctx->blend);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
pipe->delete_sampler_state(pipe, ctx->samplers[0]);
pipe->delete_sampler_state(pipe, ctx->samplers[1]);
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
FREE(ctx);
}
/**
* Copy pixel block from src surface to dst surface.
* Overlapping regions are acceptable.
* XXX need some control over blitting Z and/or stencil.
*/
void
util_blit_pixels(struct blit_state *ctx,
struct pipe_surface *src,
int srcX0, int srcY0,
int srcX1, int srcY1,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_texture texTemp, *tex;
struct pipe_surface *texSurf;
struct pipe_framebuffer_state fb;
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
const int srcLeft = MIN2(srcX0, srcX1);
const int srcTop = MIN2(srcY0, srcY1);
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
if (srcLeft != srcX0) {
/* left-right flip */
int tmp = dstX0;
dstX0 = dstX1;
dstX1 = tmp;
}
if (srcTop != srcY0) {
/* up-down flip */
int tmp = dstY0;
dstY0 = dstY1;
dstY1 = tmp;
}
/*
* XXX for now we're always creating a temporary texture.
* Strictly speaking that's not always needed.
*/
/* create temp texture */
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = PIPE_TEXTURE_2D;
texTemp.format = src->format;
texTemp.last_level = 0;
texTemp.width[0] = srcW;
texTemp.height[0] = srcH;
texTemp.depth[0] = 1;
texTemp.compressed = 0;
texTemp.cpp = pf_get_bits(src->format) / 8;
tex = screen->texture_create(screen, &texTemp);
if (!tex)
return;
texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0);
/* load temp texture */
pipe->surface_copy(pipe, FALSE,
texSurf, 0, 0, /* dest */
src, srcLeft, srcTop, /* src */
srcW, srcH); /* size */
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
fb.cbufs[0] = dst;
pipe->set_framebuffer_state(pipe, &fb);
/* sampler */
if (filter == PIPE_TEX_MIPFILTER_NEAREST)
pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]);
else
pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]);
/* texture */
pipe->set_sampler_textures(pipe, 1, &tex);
/* shaders */
pipe->bind_fs_state(pipe, ctx->fs);
pipe->bind_vs_state(pipe, ctx->vs);
/* misc state */
pipe->bind_blend_state(pipe, ctx->blend);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
/* draw quad */
util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z);
/* unbind */
pipe->set_sampler_textures(pipe, 0, NULL);
pipe->bind_sampler_states(pipe, 0, NULL);
/* free stuff */
pipe_surface_reference(&texSurf, NULL);
screen->texture_release(screen, &tex);
/* Note: caller must restore pipe/gallium state at this time */
}

View file

@ -0,0 +1,60 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef U_BLIT_H
#define U_BLIT_H
struct pipe_context;
struct pipe_surface;
struct blit_state;
extern struct blit_state *
util_create_blit(struct pipe_context *pipe);
extern void
util_destroy_blit(struct blit_state *ctx);
extern void
util_blit_pixels(struct blit_state *ctx,
struct pipe_surface *src,
int srcX0, int srcY0,
int srcX1, int srcY1,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter);
#endif

View file

@ -0,0 +1,112 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_winsys.h"
#include "util/u_draw_quad.h"
/**
* Draw screen-aligned textured quad.
*/
void
util_draw_texquad(struct pipe_context *pipe,
float x0, float y0, float x1, float y1, float z)
{
struct pipe_buffer *vbuf;
struct pipe_vertex_buffer vbuffer;
struct pipe_vertex_element velement;
uint numAttribs = 2, vertexBytes, i, j;
float *v;
vertexBytes = 4 * (4 * numAttribs * sizeof(float));
/* XXX create one-time */
vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
PIPE_BUFFER_USAGE_VERTEX, vertexBytes);
assert(vbuf);
v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
/*
* Load vertex buffer
*/
for (i = j = 0; i < 4; i++) {
v[j + 2] = z; /* z */
v[j + 3] = 1.0; /* w */
v[j + 6] = 0.0; /* r */
v[j + 7] = 1.0; /* q */
j += 8;
}
v[0] = x0;
v[1] = y0;
v[4] = 0.0; /*s*/
v[5] = 0.0; /*t*/
v[8] = x1;
v[9] = y0;
v[12] = 1.0;
v[13] = 0.0;
v[16] = x1;
v[17] = y1;
v[20] = 1.0;
v[21] = 1.0;
v[24] = x0;
v[25] = y1;
v[28] = 0.0;
v[29] = 1.0;
pipe->winsys->buffer_unmap(pipe->winsys, vbuf);
/* tell pipe about the vertex buffer */
vbuffer.buffer = vbuf;
vbuffer.pitch = numAttribs * 4 * sizeof(float); /* vertex size */
vbuffer.buffer_offset = 0;
pipe->set_vertex_buffer(pipe, 0, &vbuffer);
/* tell pipe about the vertex attributes */
for (i = 0; i < numAttribs; i++) {
velement.src_offset = i * 4 * sizeof(float);
velement.vertex_buffer_index = 0;
velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
velement.nr_components = 4;
pipe->set_vertex_element(pipe, i, &velement);
}
/* draw */
pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4);
/* XXX: do one-time */
pipe_buffer_reference(pipe->winsys, &vbuf, NULL);
}

View file

@ -0,0 +1,37 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef U_DRAWQUAD_H
#define U_DRAWQUAD_H
extern void
util_draw_texquad(struct pipe_context *pipe,
float x0, float y0, float x1, float y1, float z);
#endif

View file

@ -0,0 +1,877 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* @file
* Mipmap generation utility
*
* @author Brian Paul
*/
#include "pipe/p_context.h"
#include "pipe/p_debug.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_draw_quad.h"
#include "util/u_gen_mipmap.h"
#include "util/u_simple_shaders.h"
#include "tgsi/util/tgsi_build.h"
#include "tgsi/util/tgsi_dump.h"
#include "tgsi/util/tgsi_parse.h"
struct gen_mipmap_state
{
struct pipe_context *pipe;
void *blend;
void *depthstencil;
void *rasterizer;
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
struct pipe_sampler_state *fs;
};
enum dtype
{
UBYTE,
UBYTE_3_3_2,
USHORT,
USHORT_4_4_4_4,
USHORT_5_6_5,
USHORT_1_5_5_5_REV,
UINT,
FLOAT,
HALF_FLOAT
};
typedef ushort half_float;
#if 0
extern half_float
float_to_half(float f);
extern float
half_to_float(half_float h);
#endif
/**
* Average together two rows of a source image to produce a single new
* row in the dest image. It's legal for the two source rows to point
* to the same data. The source width must be equal to either the
* dest width or two times the dest width.
* \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
* \param comps number of components per pixel (1..4)
*/
static void
do_row(enum dtype datatype, uint comps, int srcWidth,
const void *srcRowA, const void *srcRowB,
int dstWidth, void *dstRow)
{
const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
assert(comps >= 1);
assert(comps <= 4);
/* This assertion is no longer valid with non-power-of-2 textures
assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
*/
if (datatype == UBYTE && comps == 4) {
uint i, j, k;
const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
}
}
else if (datatype == UBYTE && comps == 3) {
uint i, j, k;
const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
}
}
else if (datatype == UBYTE && comps == 2) {
uint i, j, k;
const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
}
}
else if (datatype == UBYTE && comps == 1) {
uint i, j, k;
const ubyte *rowA = (const ubyte *) srcRowA;
const ubyte *rowB = (const ubyte *) srcRowB;
ubyte *dst = (ubyte *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
}
}
else if (datatype == USHORT && comps == 4) {
uint i, j, k;
const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
ushort(*dst)[4] = (ushort(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
}
}
else if (datatype == USHORT && comps == 3) {
uint i, j, k;
const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
ushort(*dst)[3] = (ushort(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
}
}
else if (datatype == USHORT && comps == 2) {
uint i, j, k;
const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
ushort(*dst)[2] = (ushort(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
}
}
else if (datatype == USHORT && comps == 1) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
}
}
else if (datatype == FLOAT && comps == 4) {
uint i, j, k;
const float(*rowA)[4] = (const float(*)[4]) srcRowA;
const float(*rowB)[4] = (const float(*)[4]) srcRowB;
float(*dst)[4] = (float(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
dst[i][2] = (rowA[j][2] + rowA[k][2] +
rowB[j][2] + rowB[k][2]) * 0.25F;
dst[i][3] = (rowA[j][3] + rowA[k][3] +
rowB[j][3] + rowB[k][3]) * 0.25F;
}
}
else if (datatype == FLOAT && comps == 3) {
uint i, j, k;
const float(*rowA)[3] = (const float(*)[3]) srcRowA;
const float(*rowB)[3] = (const float(*)[3]) srcRowB;
float(*dst)[3] = (float(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
dst[i][2] = (rowA[j][2] + rowA[k][2] +
rowB[j][2] + rowB[k][2]) * 0.25F;
}
}
else if (datatype == FLOAT && comps == 2) {
uint i, j, k;
const float(*rowA)[2] = (const float(*)[2]) srcRowA;
const float(*rowB)[2] = (const float(*)[2]) srcRowB;
float(*dst)[2] = (float(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
}
}
else if (datatype == FLOAT && comps == 1) {
uint i, j, k;
const float *rowA = (const float *) srcRowA;
const float *rowB = (const float *) srcRowB;
float *dst = (float *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
}
}
#if 0
else if (datatype == HALF_FLOAT && comps == 4) {
uint i, j, k, comp;
const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
half_float(*dst)[4] = (half_float(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 4; comp++) {
float aj, ak, bj, bk;
aj = half_to_float(rowA[j][comp]);
ak = half_to_float(rowA[k][comp]);
bj = half_to_float(rowB[j][comp]);
bk = half_to_float(rowB[k][comp]);
dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == HALF_FLOAT && comps == 3) {
uint i, j, k, comp;
const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
half_float(*dst)[3] = (half_float(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 3; comp++) {
float aj, ak, bj, bk;
aj = half_to_float(rowA[j][comp]);
ak = half_to_float(rowA[k][comp]);
bj = half_to_float(rowB[j][comp]);
bk = half_to_float(rowB[k][comp]);
dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == HALF_FLOAT && comps == 2) {
uint i, j, k, comp;
const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
half_float(*dst)[2] = (half_float(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 2; comp++) {
float aj, ak, bj, bk;
aj = half_to_float(rowA[j][comp]);
ak = half_to_float(rowA[k][comp]);
bj = half_to_float(rowB[j][comp]);
bk = half_to_float(rowB[k][comp]);
dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == HALF_FLOAT && comps == 1) {
uint i, j, k;
const half_float *rowA = (const half_float *) srcRowA;
const half_float *rowB = (const half_float *) srcRowB;
half_float *dst = (half_float *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
float aj, ak, bj, bk;
aj = half_to_float(rowA[j]);
ak = half_to_float(rowA[k]);
bj = half_to_float(rowB[j]);
bk = half_to_float(rowB[k]);
dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
#endif
else if (datatype == UINT && comps == 1) {
uint i, j, k;
const uint *rowA = (const uint *) srcRowA;
const uint *rowB = (const uint *) srcRowB;
uint *dst = (uint *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
}
}
else if (datatype == USHORT_5_6_5 && comps == 3) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0x1f;
const int rowAg0 = (rowA[j] >> 5) & 0x3f;
const int rowAg1 = (rowA[k] >> 5) & 0x3f;
const int rowBg0 = (rowB[j] >> 5) & 0x3f;
const int rowBg1 = (rowB[k] >> 5) & 0x3f;
const int rowAb0 = (rowA[j] >> 11) & 0x1f;
const int rowAb1 = (rowA[k] >> 11) & 0x1f;
const int rowBb0 = (rowB[j] >> 11) & 0x1f;
const int rowBb1 = (rowB[k] >> 11) & 0x1f;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
dst[i] = (blue << 11) | (green << 5) | red;
}
}
else if (datatype == USHORT_4_4_4_4 && comps == 4) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0xf;
const int rowAr1 = rowA[k] & 0xf;
const int rowBr0 = rowB[j] & 0xf;
const int rowBr1 = rowB[k] & 0xf;
const int rowAg0 = (rowA[j] >> 4) & 0xf;
const int rowAg1 = (rowA[k] >> 4) & 0xf;
const int rowBg0 = (rowB[j] >> 4) & 0xf;
const int rowBg1 = (rowB[k] >> 4) & 0xf;
const int rowAb0 = (rowA[j] >> 8) & 0xf;
const int rowAb1 = (rowA[k] >> 8) & 0xf;
const int rowBb0 = (rowB[j] >> 8) & 0xf;
const int rowBb1 = (rowB[k] >> 8) & 0xf;
const int rowAa0 = (rowA[j] >> 12) & 0xf;
const int rowAa1 = (rowA[k] >> 12) & 0xf;
const int rowBa0 = (rowB[j] >> 12) & 0xf;
const int rowBa1 = (rowB[k] >> 12) & 0xf;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
}
}
else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0xf;
const int rowAg0 = (rowA[j] >> 5) & 0x1f;
const int rowAg1 = (rowA[k] >> 5) & 0x1f;
const int rowBg0 = (rowB[j] >> 5) & 0x1f;
const int rowBg1 = (rowB[k] >> 5) & 0x1f;
const int rowAb0 = (rowA[j] >> 10) & 0x1f;
const int rowAb1 = (rowA[k] >> 10) & 0x1f;
const int rowBb0 = (rowB[j] >> 10) & 0x1f;
const int rowBb1 = (rowB[k] >> 10) & 0x1f;
const int rowAa0 = (rowA[j] >> 15) & 0x1;
const int rowAa1 = (rowA[k] >> 15) & 0x1;
const int rowBa0 = (rowB[j] >> 15) & 0x1;
const int rowBa1 = (rowB[k] >> 15) & 0x1;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
}
}
else if (datatype == UBYTE_3_3_2 && comps == 3) {
uint i, j, k;
const ubyte *rowA = (const ubyte *) srcRowA;
const ubyte *rowB = (const ubyte *) srcRowB;
ubyte *dst = (ubyte *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x3;
const int rowAr1 = rowA[k] & 0x3;
const int rowBr0 = rowB[j] & 0x3;
const int rowBr1 = rowB[k] & 0x3;
const int rowAg0 = (rowA[j] >> 2) & 0x7;
const int rowAg1 = (rowA[k] >> 2) & 0x7;
const int rowBg0 = (rowB[j] >> 2) & 0x7;
const int rowBg1 = (rowB[k] >> 2) & 0x7;
const int rowAb0 = (rowA[j] >> 5) & 0x7;
const int rowAb1 = (rowA[k] >> 5) & 0x7;
const int rowBb0 = (rowB[j] >> 5) & 0x7;
const int rowBb1 = (rowB[k] >> 5) & 0x7;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
dst[i] = (blue << 5) | (green << 2) | red;
}
}
else {
debug_printf("bad format in do_row()");
}
}
static void
format_to_type_comps(enum pipe_format pformat,
enum dtype *datatype, uint *comps)
{
switch (pformat) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
*datatype = UBYTE;
*comps = 4;
return;
case PIPE_FORMAT_A1R5G5B5_UNORM:
*datatype = USHORT_1_5_5_5_REV;
*comps = 4;
return;
case PIPE_FORMAT_A4R4G4B4_UNORM:
*datatype = USHORT_4_4_4_4;
*comps = 4;
return;
case PIPE_FORMAT_R5G6B5_UNORM:
*datatype = USHORT_5_6_5;
*comps = 3;
return;
case PIPE_FORMAT_U_L8:
case PIPE_FORMAT_U_A8:
case PIPE_FORMAT_U_I8:
*datatype = UBYTE;
*comps = 1;
return;
case PIPE_FORMAT_U_A8_L8:
*datatype = UBYTE;
*comps = 2;
return;
default:
assert(0);
}
}
static void
reduce_1d(enum pipe_format pformat,
int srcWidth, const ubyte *srcPtr,
int dstWidth, ubyte *dstPtr)
{
enum dtype datatype;
uint comps;
format_to_type_comps(pformat, &datatype, &comps);
/* we just duplicate the input row, kind of hack, saves code */
do_row(datatype, comps,
srcWidth, srcPtr, srcPtr,
dstWidth, dstPtr);
}
/**
* Strides are in bytes. If zero, it'll be computed as width * bpp.
*/
static void
reduce_2d(enum pipe_format pformat,
int srcWidth, int srcHeight,
int srcRowStride, const ubyte *srcPtr,
int dstWidth, int dstHeight,
int dstRowStride, ubyte *dstPtr)
{
enum dtype datatype;
uint comps;
const int bpt = pf_get_size(pformat);
const ubyte *srcA, *srcB;
ubyte *dst;
int row;
format_to_type_comps(pformat, &datatype, &comps);
if (!srcRowStride)
srcRowStride = bpt * srcWidth;
if (!dstRowStride)
dstRowStride = bpt * dstWidth;
/* Compute src and dst pointers */
srcA = srcPtr;
if (srcHeight > 1)
srcB = srcA + srcRowStride;
else
srcB = srcA;
dst = dstPtr;
for (row = 0; row < dstHeight; row++) {
do_row(datatype, comps,
srcWidth, srcA, srcB,
dstWidth, dst);
srcA += 2 * srcRowStride;
srcB += 2 * srcRowStride;
dst += dstRowStride;
}
}
static void
make_1d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_winsys *winsys = pipe->winsys;
const uint zslice = 0;
uint dstLevel;
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_surface *srcSurf, *dstSurf;
void *srcMap, *dstMap;
srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
+ srcSurf->offset);
dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
+ dstSurf->offset);
reduce_1d(pt->format,
srcSurf->width, srcMap,
dstSurf->width, dstMap);
winsys->buffer_unmap(winsys, srcSurf->buffer);
winsys->buffer_unmap(winsys, dstSurf->buffer);
pipe_surface_reference(&srcSurf, NULL);
pipe_surface_reference(&dstSurf, NULL);
}
}
static void
make_2d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_winsys *winsys = pipe->winsys;
const uint zslice = 0;
uint dstLevel;
const int bpt = pf_get_size(pt->format);
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_surface *srcSurf, *dstSurf;
ubyte *srcMap, *dstMap;
srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
+ srcSurf->offset);
dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
+ dstSurf->offset);
reduce_2d(pt->format,
srcSurf->width, srcSurf->height,
srcSurf->pitch * bpt, srcMap,
dstSurf->width, dstSurf->height,
dstSurf->pitch * bpt, dstMap);
winsys->buffer_unmap(winsys, srcSurf->buffer);
winsys->buffer_unmap(winsys, dstSurf->buffer);
pipe_surface_reference(&srcSurf, NULL);
pipe_surface_reference(&dstSurf, NULL);
}
}
static void
make_3d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
{
}
static void
fallback_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
{
switch (pt->target) {
case PIPE_TEXTURE_1D:
make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_CUBE:
make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_3D:
make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
break;
default:
assert(0);
}
}
/**
* Create a mipmap generation context.
* The idea is to create one of these and re-use it each time we need to
* generate a mipmap.
*/
struct gen_mipmap_state *
util_create_gen_mipmap(struct pipe_context *pipe)
{
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state depthstencil;
struct pipe_rasterizer_state rasterizer;
struct gen_mipmap_state *ctx;
ctx = CALLOC_STRUCT(gen_mipmap_state);
if (!ctx)
return NULL;
ctx->pipe = pipe;
/* we don't use blending, but need to set valid values */
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask = PIPE_MASK_RGBA;
ctx->blend = pipe->create_blend_state(pipe, &blend);
/* depth/stencil/alpha */
memset(&depthstencil, 0, sizeof(depthstencil));
ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
/* rasterizer */
memset(&rasterizer, 0, sizeof(rasterizer));
rasterizer.front_winding = PIPE_WINDING_CW;
rasterizer.cull_mode = PIPE_WINDING_NONE;
rasterizer.bypass_clipping = 1; /* bypasses viewport too */
//rasterizer.bypass_vs = 1;
ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
#if 0
/* viewport */
ctx->viewport.scale[0] = 1.0;
ctx->viewport.scale[1] = 1.0;
ctx->viewport.scale[2] = 1.0;
ctx->viewport.scale[3] = 1.0;
ctx->viewport.translate[0] = 0.0;
ctx->viewport.translate[1] = 0.0;
ctx->viewport.translate[2] = 0.0;
ctx->viewport.translate[3] = 0.0;
#endif
/* vertex shader */
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0 };
ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
semantic_indexes);
}
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe);
return ctx;
}
/**
* Destroy a mipmap generation context
*/
void
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
pipe->delete_blend_state(pipe, ctx->blend);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
FREE(ctx);
}
#if 0
static void
simple_viewport(struct pipe_context *pipe, uint width, uint height)
{
struct pipe_viewport_state vp;
vp.scale[0] = 0.5 * width;
vp.scale[1] = -0.5 * height;
vp.scale[2] = 1.0;
vp.scale[3] = 1.0;
vp.translate[0] = 0.5 * width;
vp.translate[1] = 0.5 * height;
vp.translate[2] = 0.0;
vp.translate[3] = 0.0;
pipe->set_viewport_state(pipe, &vp);
}
#endif
/**
* Generate mipmap images. It's assumed all needed texture memory is
* already allocated.
*
* \param pt the texture to generate mipmap levels for
* \param face which cube face to generate mipmaps for (0 for non-cube maps)
* \param baseLevel the first mipmap level to use as a src
* \param lastLevel the last mipmap level to generate
*/
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
struct pipe_sampler_state sampler;
void *sampler_cso;
uint dstLevel;
uint zslice = 0;
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, pt->format, PIPE_SURFACE)) {
fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
return;
}
/* init framebuffer state */
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
/* sampler state */
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.normalized_coords = 1;
/* bind our state */
pipe->bind_blend_state(pipe, ctx->blend);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
pipe->bind_vs_state(pipe, ctx->vs);
pipe->bind_fs_state(pipe, ctx->fs);
#if 0
pipe->set_viewport_state(pipe, &ctx->viewport);
#endif
/*
* XXX for small mipmap levels, it may be faster to use the software
* fallback path...
*/
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
/*
* Setup framebuffer / dest surface
*/
fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
pipe->set_framebuffer_state(pipe, &fb);
/*
* Setup sampler state
* Note: we should only have to set the min/max LOD clamps to ensure
* we grab texels from the right mipmap level. But some hardware
* has trouble with min clamping so we also set the lod_bias to
* try to work around that.
*/
sampler.min_lod = sampler.max_lod = (float) srcLevel;
sampler.lod_bias = (float) srcLevel;
sampler_cso = pipe->create_sampler_state(pipe, &sampler);
pipe->bind_sampler_states(pipe, 1, &sampler_cso);
#if 0
simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
#endif
pipe->set_sampler_textures(pipe, 1, &pt);
/* quad coords in window coords (bypassing clipping, viewport mapping) */
util_draw_texquad(pipe,
0.0F, 0.0F, /* x0, y0 */
(float) pt->width[dstLevel], /* x1 */
(float) pt->height[dstLevel], /* y1 */
0.0F); /* z */
pipe->flush(pipe, PIPE_FLUSH_WAIT);
/*pipe->texture_update(pipe, pt); not really needed */
pipe->delete_sampler_state(pipe, sampler_cso);
}
/* Note: caller must restore pipe/gallium state at this time */
}

View file

@ -0,0 +1,52 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef U_GENMIPMAP_H
#define U_GENMIPMAP_H
#include "pipe/p_state.h"
struct gen_mipmap_state;
extern struct gen_mipmap_state *
util_create_gen_mipmap(struct pipe_context *pipe);
extern void
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
extern void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel);
#endif

View file

@ -226,9 +226,13 @@ handle_table_remove(struct handle_table *ht,
index = handle - 1;
object = ht->objects[index];
assert(object);
if(!object) {
/* XXX: this warning may be noisy for legitimate use -- remove later */
debug_warning("removing empty handle");
return;
}
if(object && ht->destroy)
if(ht->destroy)
ht->destroy(object);
ht->objects[index] = NULL;
@ -237,6 +241,28 @@ handle_table_remove(struct handle_table *ht,
}
unsigned
handle_table_get_next_handle(struct handle_table *ht,
unsigned handle)
{
unsigned index;
for(index = handle; index < ht->size; ++index) {
if(!ht->objects[index])
return index + 1;
}
return 0;
}
unsigned
handle_table_get_first_handle(struct handle_table *ht)
{
return handle_table_get_next_handle(ht, 0);
}
void
handle_table_destroy(struct handle_table *ht)
{

View file

@ -100,6 +100,15 @@ void
handle_table_destroy(struct handle_table *ht);
unsigned
handle_table_get_first_handle(struct handle_table *ht);
unsigned
handle_table_get_next_handle(struct handle_table *ht,
unsigned handle);
#ifdef __cplusplus
}
#endif

View file

@ -187,6 +187,28 @@ hash_table_remove(struct hash_table *ht,
}
enum pipe_error
hash_table_foreach(struct hash_table *ht,
enum pipe_error (*callback)(void *key, void *value, void *data),
void *data)
{
struct cso_hash_iter iter;
struct hash_table_item *item;
enum pipe_error result;
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct hash_table_item *)cso_hash_iter_data(iter);
result = callback(item->key, item->value, data);
if(result != PIPE_OK)
return result;
iter = cso_hash_iter_next(iter);
}
return PIPE_OK;
}
void
hash_table_destroy(struct hash_table *ht)
{
@ -196,4 +218,3 @@ hash_table_destroy(struct hash_table *ht)
FREE(ht);
}

View file

@ -75,6 +75,11 @@ hash_table_remove(struct hash_table *ht,
void *key);
enum pipe_error
hash_table_foreach(struct hash_table *ht,
enum pipe_error (*callback)(void *key, void *value, void *data),
void *data);
void
hash_table_destroy(struct hash_table *ht);

View file

@ -0,0 +1,133 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* @file
* Functions to produce packed colors/Z from floats.
*/
#ifndef U_PACK_COLOR_H
#define U_PACK_COLOR_H
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
/**
* Note rgba outside [0,1] will be clamped for int pixel formats.
*/
static INLINE void
util_pack_color(const float rgba[4], enum pipe_format format, void *dest)
{
ubyte r, g, b, a;
if (pf_size_x(format) <= 8) {
/* format uses 8-bit components or less */
UNCLAMPED_FLOAT_TO_UBYTE(r, rgba[0]);
UNCLAMPED_FLOAT_TO_UBYTE(g, rgba[1]);
UNCLAMPED_FLOAT_TO_UBYTE(b, rgba[2]);
UNCLAMPED_FLOAT_TO_UBYTE(a, rgba[3]);
}
switch (format) {
case PIPE_FORMAT_R8G8B8A8_UNORM:
{
uint *d = (uint *) dest;
*d = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
case PIPE_FORMAT_A8R8G8B8_UNORM:
{
uint *d = (uint *) dest;
*d = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
uint *d = (uint *) dest;
*d = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
case PIPE_FORMAT_R5G6B5_UNORM:
{
ushort *d = (ushort *) dest;
*d = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
return;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *d = (float *) dest;
d[0] = rgba[0];
d[1] = rgba[1];
d[2] = rgba[2];
d[3] = rgba[3];
}
return;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
float *d = (float *) dest;
d[0] = rgba[0];
d[1] = rgba[1];
d[2] = rgba[2];
}
return;
/* XXX lots more cases to add */
default:
debug_printf("gallium: unhandled format in util_pack_color()");
}
}
/**
* Note: it's assumed that z is in [0,1]
*/
static INLINE uint
util_pack_z(enum pipe_format format, double z)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
return (uint) (z * 0xffff);
case PIPE_FORMAT_Z32_UNORM:
/* special-case to avoid overflow */
if (z == 1.0)
return 0xffffffff;
else
return (uint) (z * 0xffffffff);
case PIPE_FORMAT_S8Z24_UNORM:
return (uint) (z * 0xffffff);
case PIPE_FORMAT_Z24S8_UNORM:
return ((uint) (z * 0xffffff)) << 8;
default:
debug_printf("gallium: unhandled fomrat in util_pack_z()");
return 0;
}
}
#endif /* U_PACK_COLOR_H */

View file

@ -0,0 +1,263 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* @file
* Simple vertex/fragment shader generators.
*
* @author Brian Paul
*/
#include "pipe/p_context.h"
#include "pipe/p_debug.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_simple_shaders.h"
#include "tgsi/util/tgsi_build.h"
#include "tgsi/util/tgsi_dump.h"
#include "tgsi/util/tgsi_parse.h"
/**
* Make simple vertex pass-through shader.
*/
void *
util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes)
{
uint maxTokens = 100;
struct tgsi_token *tokens;
struct tgsi_header *header;
struct tgsi_processor *processor;
struct tgsi_full_declaration decl;
struct tgsi_full_instruction inst;
const uint procType = TGSI_PROCESSOR_VERTEX;
uint ti, i;
struct pipe_shader_state shader;
tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
/* shader header
*/
*(struct tgsi_version *) &tokens[0] = tgsi_build_version();
header = (struct tgsi_header *) &tokens[1];
*header = tgsi_build_header();
processor = (struct tgsi_processor *) &tokens[2];
*processor = tgsi_build_processor( procType, header );
ti = 3;
/* declare inputs */
for (i = 0; i < num_attribs; i++) {
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
/*
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
decl.Semantic.SemanticIndex = 0;
*/
decl.u.DeclarationRange.First =
decl.u.DeclarationRange.Last = 0;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
}
/* declare outputs */
for (i = 0; i < num_attribs; i++) {
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_OUTPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = semantic_names[i];
decl.Semantic.SemanticIndex = semantic_indexes[i];
decl.u.DeclarationRange.First =
decl.u.DeclarationRange.Last = 0;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
}
/* emit MOV instructions */
for (i = 0; i < num_attribs; i++) {
/* MOVE out[i], in[i]; */
inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_MOV;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
inst.FullDstRegisters[0].DstRegister.Index = i;
inst.Instruction.NumSrcRegs = 1;
inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
inst.FullSrcRegisters[0].SrcRegister.Index = i;
ti += tgsi_build_full_instruction(&inst,
&tokens[ti],
header,
maxTokens - ti );
}
/* END instruction */
inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_END;
inst.Instruction.NumDstRegs = 0;
inst.Instruction.NumSrcRegs = 0;
ti += tgsi_build_full_instruction(&inst,
&tokens[ti],
header,
maxTokens - ti );
#if 0 /*debug*/
tgsi_dump(tokens, 0);
#endif
shader.tokens = tokens;
return pipe->create_vs_state(pipe, &shader);
}
/**
* Make simple fragment texture shader:
* TEX OUT[0], IN[0], SAMP[0], 2D;
* END;
*/
void *
util_make_fragment_tex_shader(struct pipe_context *pipe)
{
uint maxTokens = 100;
struct tgsi_token *tokens;
struct tgsi_header *header;
struct tgsi_processor *processor;
struct tgsi_full_declaration decl;
struct tgsi_full_instruction inst;
const uint procType = TGSI_PROCESSOR_FRAGMENT;
uint ti;
struct pipe_shader_state shader;
tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
/* shader header
*/
*(struct tgsi_version *) &tokens[0] = tgsi_build_version();
header = (struct tgsi_header *) &tokens[1];
*header = tgsi_build_header();
processor = (struct tgsi_processor *) &tokens[2];
*processor = tgsi_build_processor( procType, header );
ti = 3;
/* declare TEX[0] input */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
decl.Semantic.SemanticIndex = 0;
/* XXX this could be linear... */
decl.Declaration.Interpolate = 1;
decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
decl.u.DeclarationRange.First =
decl.u.DeclarationRange.Last = 0;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
/* declare color[0] output */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_OUTPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
decl.Semantic.SemanticIndex = 0;
decl.u.DeclarationRange.First =
decl.u.DeclarationRange.Last = 0;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
/* declare sampler */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.u.DeclarationRange.First =
decl.u.DeclarationRange.Last = 0;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
/* TEX instruction */
inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_TEX;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
inst.FullDstRegisters[0].DstRegister.Index = 0;
inst.Instruction.NumSrcRegs = 2;
inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
inst.FullSrcRegisters[0].SrcRegister.Index = 0;
inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
inst.FullSrcRegisters[1].SrcRegister.Index = 0;
ti += tgsi_build_full_instruction(&inst,
&tokens[ti],
header,
maxTokens - ti );
/* END instruction */
inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_END;
inst.Instruction.NumDstRegs = 0;
inst.Instruction.NumSrcRegs = 0;
ti += tgsi_build_full_instruction(&inst,
&tokens[ti],
header,
maxTokens - ti );
#if 0 /*debug*/
tgsi_dump(tokens, 0);
#endif
shader.tokens = tokens;
return pipe->create_fs_state(pipe, &shader);
}

View file

@ -0,0 +1,52 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef U_SIMPLE_SHADERS_H
#define U_SIMPLE_SHADERS_H
#include "pipe/p_compiler.h"
struct pipe_context;
extern void *
util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes);
extern void *
util_make_fragment_tex_shader(struct pipe_context *pipe);
#endif

View file

@ -104,6 +104,16 @@
/**
*/
struct cell_command_depth_stencil_alpha_test {
uint64_t base; /**< Effective address of code start. */
unsigned size; /**< Size in bytes of test code. */
unsigned read_depth; /**< Flag: should depth be read? */
unsigned read_stencil; /**< Flag: should stencil be read? */
};
/**
* Tell SPUs about the framebuffer size, location
*/

View file

@ -27,6 +27,7 @@ SOURCES = \
cell_flush.c \
cell_state_derived.c \
cell_state_emit.c \
cell_state_per_fragment.c \
cell_state_shader.c \
cell_pipe_state.c \
cell_screen.c \

View file

@ -57,16 +57,37 @@ struct cell_fragment_shader_state
};
struct cell_blend_state {
struct pipe_blend_state base;
/**
* Generated code to perform alpha blending
*/
struct spe_function code;
};
struct cell_depth_stencil_alpha_state {
struct pipe_depth_stencil_alpha_state base;
/**
* Generated code to perform alpha, stencil, and depth testing on the SPE
*/
struct spe_function code;
};
struct cell_context
{
struct pipe_context pipe;
struct cell_winsys *winsys;
const struct pipe_blend_state *blend;
const struct cell_blend_state *blend;
const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
uint num_samplers;
const struct pipe_depth_stencil_alpha_state *depth_stencil;
const struct cell_depth_stencil_alpha_state *depth_stencil;
const struct pipe_rasterizer_state *rasterizer;
const struct cell_vertex_shader_state *vs;
const struct cell_fragment_shader_state *fs;

View file

@ -36,6 +36,7 @@
#include "cell_context.h"
#include "cell_state.h"
#include "cell_texture.h"
#include "cell_state_per_fragment.h"
@ -43,7 +44,12 @@ static void *
cell_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *blend)
{
return mem_dup(blend, sizeof(*blend));
struct cell_blend_state *cb = MALLOC(sizeof(struct cell_blend_state));
(void) memcpy(cb, blend, sizeof(*blend));
cb->code.store = NULL;
return cb;
}
@ -54,7 +60,7 @@ cell_bind_blend_state(struct pipe_context *pipe, void *blend)
draw_flush(cell->draw);
cell->blend = (const struct pipe_blend_state *)blend;
cell->blend = (const struct cell_blend_state *)blend;
cell->dirty |= CELL_NEW_BLEND;
}
@ -63,7 +69,10 @@ cell_bind_blend_state(struct pipe_context *pipe, void *blend)
static void
cell_delete_blend_state(struct pipe_context *pipe, void *blend)
{
FREE(blend);
struct cell_blend_state *cb = (struct cell_blend_state *) blend;
spe_release_func(& cb->code);
FREE(cb);
}
@ -87,7 +96,13 @@ static void *
cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *depth_stencil)
{
return mem_dup(depth_stencil, sizeof(*depth_stencil));
struct cell_depth_stencil_alpha_state *cdsa =
MALLOC(sizeof(struct cell_depth_stencil_alpha_state));
(void) memcpy(cdsa, depth_stencil, sizeof(*depth_stencil));
cdsa->code.store = NULL;
return cdsa;
}
@ -96,12 +111,16 @@ cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct cell_context *cell = cell_context(pipe);
struct cell_depth_stencil_alpha_state *cdsa =
(struct cell_depth_stencil_alpha_state *) depth_stencil;
draw_flush(cell->draw);
cell->depth_stencil
= (const struct pipe_depth_stencil_alpha_state *) depth_stencil;
if ((cdsa != NULL) && (cdsa->code.store == NULL)) {
cell_generate_depth_stencil_test(cdsa);
}
cell->depth_stencil = cdsa;
cell->dirty |= CELL_NEW_DEPTH_STENCIL;
}
@ -109,7 +128,11 @@ cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
static void
cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *depth)
{
FREE(depth);
struct cell_depth_stencil_alpha_state *cdsa =
(struct cell_depth_stencil_alpha_state *) depth;
spe_release_func(& cdsa->code);
FREE(cdsa);
}

View file

@ -71,9 +71,24 @@ cell_emit_state(struct cell_context *cell)
}
if (cell->dirty & CELL_NEW_DEPTH_STENCIL) {
emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL,
cell->depth_stencil,
sizeof(struct pipe_depth_stencil_alpha_state));
struct cell_command_depth_stencil_alpha_test dsat;
if (cell->depth_stencil != NULL) {
dsat.base = (intptr_t) cell->depth_stencil->code.store;
dsat.size = (char *) cell->depth_stencil->code.csr
- (char *) cell->depth_stencil->code.store;
dsat.read_depth = TRUE;
dsat.read_stencil = FALSE;
} else {
dsat.base = 0;
dsat.size = 0;
dsat.read_depth = FALSE;
dsat.read_stencil = FALSE;
}
emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL, &dsat,
sizeof(dsat));
}
if (cell->dirty & CELL_NEW_SAMPLER) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,35 @@
/*
* (C) Copyright IBM Corporation 2008
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef CELL_STATE_PER_FRAGMENT_H
#define CELL_STATE_PER_FRAGMENT_H
extern void
cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa);
extern void
cell_generate_alpha_blend(struct cell_blend_state *cb,
const struct pipe_blend_color *blend_color);
#endif /* CELL_STATE_PER_FRAGMENT_H */

View file

@ -19,6 +19,7 @@ SOURCES = \
spu_main.c \
spu_blend.c \
spu_dcache.c \
spu_per_fragment_op.c \
spu_render.c \
spu_texture.c \
spu_tile.c \

View file

@ -58,6 +58,9 @@ struct spu_vs_context draw;
static unsigned char attribute_fetch_code_buffer[136 * PIPE_ATTRIB_MAX]
ALIGN16_ATTRIB;
static unsigned char depth_stencil_code_buffer[4 * 64]
ALIGN16_ATTRIB;
/**
* Tell the PPU that this SPU has finished copying a buffer to
* local store and that it may be reused by the PPU.
@ -215,12 +218,19 @@ cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
if (spu.fb.depth_format == PIPE_FORMAT_Z32_UNORM)
switch (spu.fb.depth_format) {
case PIPE_FORMAT_Z32_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
spu.fb.zsize = 4;
else if (spu.fb.depth_format == PIPE_FORMAT_Z16_UNORM)
break;
case PIPE_FORMAT_Z16_UNORM:
spu.fb.zsize = 2;
else
break;
default:
spu.fb.zsize = 0;
break;
}
if (spu.fb.color_format == PIPE_FORMAT_A8R8G8B8_UNORM)
spu.color_shuffle = ((vector unsigned char) {
@ -248,14 +258,35 @@ cmd_state_blend(const struct pipe_blend_state *state)
static void
cmd_state_depth_stencil(const struct pipe_depth_stencil_alpha_state *state)
cmd_state_depth_stencil(const struct cell_command_depth_stencil_alpha_test *state)
{
if (Debug)
printf("SPU %u: DEPTH_STENCIL: ztest %d\n",
spu.init.id,
state->depth.enabled);
state->read_depth);
memcpy(&spu.depth_stencil, state, sizeof(*state));
ASSERT_ALIGN16(state->base);
if (state->size != 0) {
mfc_get(depth_stencil_code_buffer,
(unsigned int) state->base, /* src */
ROUNDUP16(state->size),
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
} else {
/* If there is no code, emit a return instruction.
*/
depth_stencil_code_buffer[0] = 0x35;
depth_stencil_code_buffer[1] = 0x00;
depth_stencil_code_buffer[2] = 0x00;
depth_stencil_code_buffer[3] = 0x00;
}
spu.frag_test = (frag_test_func) depth_stencil_code_buffer;
spu.read_depth = state->read_depth;
spu.read_stencil = state->read_stencil;
}
@ -415,9 +446,9 @@ cmd_batch(uint opcode)
pos += (1 + ROUNDUP8(sizeof(struct pipe_blend_state)) / 8);
break;
case CELL_CMD_STATE_DEPTH_STENCIL:
cmd_state_depth_stencil((struct pipe_depth_stencil_alpha_state *)
cmd_state_depth_stencil((struct cell_command_depth_stencil_alpha_test *)
&buffer[pos+1]);
pos += (1 + ROUNDUP8(sizeof(struct pipe_depth_stencil_alpha_state)) / 8);
pos += (1 + ROUNDUP8(sizeof(struct cell_command_depth_stencil_alpha_test)) / 8);
break;
case CELL_CMD_STATE_SAMPLER:
cmd_state_sampler((struct pipe_sampler_state *) &buffer[pos+1]);

View file

@ -56,6 +56,17 @@ typedef union {
#define TILE_STATUS_GETTING 5 /**< mfc_get() called but not yet arrived */
struct spu_frag_test_results {
qword mask;
qword depth;
qword stencil;
};
typedef struct spu_frag_test_results (*frag_test_func)(qword frag_mask,
qword pixel_depth, qword pixel_stencil, qword frag_depth,
qword frag_alpha, qword facing);
struct spu_framebuffer {
void *color_start; /**< addr of color surface in main memory */
void *depth_start; /**< addr of depth surface in main memory */
@ -79,8 +90,9 @@ struct spu_global
struct cell_init_info init;
struct spu_framebuffer fb;
struct pipe_blend_state blend_stencil;
struct pipe_depth_stencil_alpha_state depth_stencil;
boolean read_depth;
boolean read_stencil;
frag_test_func frag_test;
struct pipe_blend_state blend;
struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
struct cell_command_texture texture;

View file

@ -0,0 +1,211 @@
/*
* (C) Copyright IBM Corporation 2008
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file spu_per_fragment_op.c
* SPU implementation various per-fragment operations.
*
* \author Ian Romanick <idr@us.ibm.com>
*/
#include "pipe/p_format.h"
#include "spu_main.h"
#include "spu_per_fragment_op.h"
#define ZERO 0x80
static void
read_ds_quad(tile_t *buffer, unsigned x, unsigned y,
enum pipe_format depth_format, qword *depth,
qword *stencil)
{
const int ix = x / 2;
const int iy = y / 2;
switch (depth_format) {
case PIPE_FORMAT_Z16_UNORM: {
qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
const qword shuf_vec = (qword) {
ZERO, ZERO, 0, 1, ZERO, ZERO, 2, 3,
ZERO, ZERO, 4, 5, ZERO, ZERO, 6, 7
};
/* At even X values we want the first 4 shorts, and at odd X values we
* want the second 4 shorts.
*/
qword bias = (qword) spu_splats((unsigned char) ((ix & 0x01) << 3));
qword bias_mask = si_fsmbi(0x3333);
qword sv = si_a(shuf_vec, si_and(bias_mask, bias));
*depth = si_shufb(*ptr, *ptr, sv);
*stencil = si_il(0);
break;
}
case PIPE_FORMAT_Z32_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*depth = *ptr;
*stencil = si_il(0);
break;
}
case PIPE_FORMAT_Z24S8_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0xEEEE);
*depth = si_rotmai(si_and(*ptr, mask), -8);
*stencil = si_andc(*ptr, mask);
break;
}
case PIPE_FORMAT_S8Z24_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*depth = si_and(*ptr, si_fsmbi(0x7777));
*stencil = si_andi(si_roti(*ptr, 8), 0x0ff);
break;
}
default:
assert(0);
break;
}
}
static void
write_ds_quad(tile_t *buffer, unsigned x, unsigned y,
enum pipe_format depth_format,
qword depth, qword stencil)
{
const int ix = x / 2;
const int iy = y / 2;
(void) stencil;
switch (depth_format) {
case PIPE_FORMAT_Z16_UNORM: {
qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
qword sv = ((ix & 0x01) == 0)
? (qword) { 2, 3, 6, 7, 10, 11, 14, 15,
24, 25, 26, 27, 28, 29, 30, 31 }
: (qword) { 16, 17, 18, 19, 20 , 21, 22, 23,
2, 3, 6, 7, 10, 11, 14, 15 };
*ptr = si_shufb(depth, *ptr, sv);
break;
}
case PIPE_FORMAT_Z32_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*ptr = depth;
break;
}
case PIPE_FORMAT_Z24S8_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0xEEEE);
depth = si_shli(depth, 8);
*ptr = si_selb(stencil, depth, mask);
break;
}
case PIPE_FORMAT_S8Z24_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0x7777);
stencil = si_shli(stencil, 24);
*ptr = si_selb(stencil, depth, mask);
break;
}
default:
assert(0);
break;
}
}
qword
spu_do_depth_stencil(int x, int y,
qword frag_mask, qword frag_depth, qword frag_alpha,
qword facing)
{
struct spu_frag_test_results result;
qword pixel_depth;
qword pixel_stencil;
/* All of this preable code (everthing before the call to frag_test) should
* be generated on the PPU and upload to the SPU.
*/
if (spu.read_depth || spu.read_stencil) {
read_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
&pixel_depth, &pixel_stencil);
}
switch (spu.fb.depth_format) {
case PIPE_FORMAT_Z16_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x0000ffffu)));
frag_depth = si_cfltu(frag_depth, 0);
break;
case PIPE_FORMAT_Z32_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0xffffffffu)));
frag_depth = si_cfltu(frag_depth, 0);
break;
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x00ffffffu)));
frag_depth = si_cfltu(frag_depth, 0);
break;
default:
ASSERT(0);
break;
}
result = (*spu.frag_test)(frag_mask, pixel_depth, pixel_stencil,
frag_depth, frag_alpha, facing);
/* This code (everthing after the call to frag_test) should
* be generated on the PPU and upload to the SPU.
*/
if (spu.read_depth || spu.read_stencil) {
write_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
result.depth, result.stencil);
}
return result.mask;
}

View file

@ -0,0 +1,32 @@
/*
* (C) Copyright IBM Corporation 2008
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SPU_PER_FRAGMENT_OP
#define SPU_PER_FRAGMENT_OP
extern qword
spu_do_depth_stencil(int x, int y, qword frag_mask, qword frag_depth,
qword frag_alpha, qword facing);
#endif /* SPU_PER_FRAGMENT_OP */

View file

@ -98,7 +98,7 @@ my_tile(uint tx, uint ty)
static INLINE void
get_cz_tiles(uint tx, uint ty)
{
if (spu.depth_stencil.depth.enabled) {
if (spu.read_depth) {
if (spu.cur_ztile_status != TILE_STATUS_CLEAR) {
//printf("SPU %u: getting Z tile %u, %u\n", spu.init.id, tx, ty);
get_tile(tx, ty, &spu.ztile, TAG_READ_TILE_Z, 1);
@ -153,7 +153,7 @@ static INLINE void
wait_put_cz_tiles(void)
{
wait_on_mask(1 << TAG_WRITE_TILE_COLOR);
if (spu.depth_stencil.depth.enabled) {
if (spu.read_depth) {
wait_on_mask(1 << TAG_WRITE_TILE_Z);
}
}

View file

@ -56,13 +56,13 @@ clear_c_tile(tile_t *ctile)
static INLINE void
clear_z_tile(tile_t *ztile)
{
if (spu.fb.depth_format == PIPE_FORMAT_Z16_UNORM) {
if (spu.fb.zsize == 2) {
memset16((ushort*) ztile->us,
spu.fb.depth_clear_value,
TILE_SIZE * TILE_SIZE);
}
else {
ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z32_UNORM);
ASSERT(spu.fb.zsize != 0);
memset32((uint*) ztile->ui,
spu.fb.depth_clear_value,
TILE_SIZE * TILE_SIZE);

View file

@ -38,8 +38,7 @@
#include "spu_texture.h"
#include "spu_tile.h"
#include "spu_tri.h"
#include "spu_ztest.h"
#include "spu_per_fragment_op.h"
/** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
@ -264,16 +263,12 @@ do_depth_test(int x, int y, mask_t quadmask)
zvals.v = eval_z((float) x, (float) y);
if (spu.fb.depth_format == PIPE_FORMAT_Z16_UNORM) {
int ix = (x - setup.cliprect_minx) / 4;
int iy = (y - setup.cliprect_miny) / 2;
mask = spu_z16_test_less(zvals.v, &spu.ztile.us8[iy][ix], x>>1, quadmask);
}
else {
int ix = (x - setup.cliprect_minx) / 2;
int iy = (y - setup.cliprect_miny) / 2;
mask = spu_z32_test_less(zvals.v, &spu.ztile.ui4[iy][ix], quadmask);
}
mask = (mask_t) spu_do_depth_stencil(x - setup.cliprect_minx,
y - setup.cliprect_miny,
(qword) quadmask,
(qword) zvals.v,
(qword) spu_splats((unsigned char) 0x0ffu),
(qword) spu_splats((unsigned int) 0x01u));
if (spu_extract(spu_orx(mask), 0))
spu.cur_ztile_status = TILE_STATUS_DIRTY;
@ -299,7 +294,7 @@ emit_quad( int x, int y, mask_t mask )
sp->quad.first->run(sp->quad.first, &setup.quad);
#else
if (spu.depth_stencil.depth.enabled) {
if (spu.read_depth) {
mask = do_depth_test(x, y, mask);
}
@ -434,7 +429,7 @@ static void flush_spans( void )
}
ASSERT(spu.cur_ctile_status != TILE_STATUS_DEFINED);
if (spu.depth_stencil.depth.enabled) {
if (spu.read_depth) {
if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
/* wait for mfc_get() to complete */
//printf("SPU: %u: waiting for ztile\n", spu.init.id);

View file

@ -1,135 +0,0 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* Zbuffer/depth test code.
*/
#ifndef SPU_ZTEST_H
#define SPU_ZTEST_H
#ifdef __SPU__
#include <spu_intrinsics.h>
#endif
/**
* Perform Z testing for a 16-bit/value Z buffer.
*
* \param zvals vector of four fragment zvalues as floats
* \param zbuf ptr to vector of ushort[8] zbuffer values. Note that this
* contains the Z values for 2 quads, 8 pixels.
* \param x x coordinate of quad (only lsbit is significant)
* \param inMask indicates which fragments in the quad are alive
* \return new mask indicating which fragments are alive after ztest
*/
static INLINE vector unsigned int
spu_z16_test_less(vector float zvals, vector unsigned short *zbuf,
uint x, vector unsigned int inMask)
{
#define ZERO 0x80
vector unsigned int zvals_ui4, zbuf_ui4, mask;
/* convert floats to uints in [0, 65535] */
zvals_ui4 = spu_convtu(zvals, 32); /* convert to [0, 2^32] */
zvals_ui4 = spu_rlmask(zvals_ui4, -16); /* right shift 16 */
/* XXX this conditional could be removed with a bit of work */
if (x & 1) {
/* convert zbuffer values from ushorts to uints */
/* gather lower four ushorts */
zbuf_ui4 = spu_shuffle((vector unsigned int) *zbuf,
(vector unsigned int) *zbuf,
((vector unsigned char) {
ZERO, ZERO, 8, 9, ZERO, ZERO, 10, 11,
ZERO, ZERO, 12, 13, ZERO, ZERO, 14, 15}));
/* mask = (zbuf_ui4 < zvals_ui4) ? ~0 : 0 */
mask = spu_cmpgt(zbuf_ui4, zvals_ui4);
/* mask &= inMask */
mask = spu_and(mask, inMask);
/* zbuf = mask ? zval : zbuf */
zbuf_ui4 = spu_sel(zbuf_ui4, zvals_ui4, mask);
/* convert zbuffer values from uints back to ushorts, preserve lower 4 */
*zbuf = (vector unsigned short)
spu_shuffle(zbuf_ui4, (vector unsigned int) *zbuf,
((vector unsigned char) {
16, 17, 18, 19, 20, 21, 22, 23,
2, 3, 6, 7, 10, 11, 14, 15}));
}
else {
/* convert zbuffer values from ushorts to uints */
/* gather upper four ushorts */
zbuf_ui4 = spu_shuffle((vector unsigned int) *zbuf,
(vector unsigned int) *zbuf,
((vector unsigned char) {
ZERO, ZERO, 0, 1, ZERO, ZERO, 2, 3,
ZERO, ZERO, 4, 5, ZERO, ZERO, 6, 7}));
/* mask = (zbuf_ui4 < zvals_ui4) ? ~0 : 0 */
mask = spu_cmpgt(zbuf_ui4, zvals_ui4);
/* mask &= inMask */
mask = spu_and(mask, inMask);
/* zbuf = mask ? zval : zbuf */
zbuf_ui4 = spu_sel(zbuf_ui4, zvals_ui4, mask);
/* convert zbuffer values from uints back to ushorts, preserve upper 4 */
*zbuf = (vector unsigned short)
spu_shuffle(zbuf_ui4, (vector unsigned int) *zbuf,
((vector unsigned char) {
2, 3, 6, 7, 10, 11, 14, 15,
24, 25, 26, 27, 28, 29, 30, 31}));
}
return mask;
#undef ZERO
}
/**
* As above, but Zbuffer values as 32-bit uints
*/
static INLINE vector unsigned int
spu_z32_test_less(vector float zvals, vector unsigned int *zbuf_ptr,
vector unsigned int inMask)
{
vector unsigned int zvals_ui4, mask, zbuf = *zbuf_ptr;
/* convert floats to uints in [0, 0xffffffff] */
zvals_ui4 = spu_convtu(zvals, 32);
/* mask = (zbuf < zvals_ui4) ? ~0 : 0 */
mask = spu_cmpgt(zbuf, zvals_ui4);
/* mask &= inMask */
mask = spu_and(mask, inMask);
/* zbuf = mask ? zval : zbuf */
*zbuf_ptr = spu_sel(zbuf, zvals_ui4, mask);
return mask;
}
#endif /* SPU_ZTEST_H */

View file

@ -116,7 +116,7 @@ i915_vbuf_render_allocate_vertices( struct vbuf_render *render,
}
static void
static boolean
i915_vbuf_render_set_primitive( struct vbuf_render *render,
unsigned prim )
{
@ -125,15 +125,17 @@ i915_vbuf_render_set_primitive( struct vbuf_render *render,
switch(prim) {
case PIPE_PRIM_POINTS:
i915_render->hwprim = PRIM3D_POINTLIST;
break;
return TRUE;
case PIPE_PRIM_LINES:
i915_render->hwprim = PRIM3D_LINELIST;
break;
return TRUE;
case PIPE_PRIM_TRIANGLES:
i915_render->hwprim = PRIM3D_TRILIST;
break;
return TRUE;
default:
assert(0);
/* Actually, can handle a lot more just fine... Fixme.
*/
return FALSE;
}
}

View file

@ -101,11 +101,20 @@ sp_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
}
static void
static boolean
sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
cvbr->prim = prim;
if (prim == PIPE_PRIM_TRIANGLES ||
prim == PIPE_PRIM_LINES ||
prim == PIPE_PRIM_POINTS) {
cvbr->prim = prim;
return TRUE;
}
else {
return FALSE;
}
}
@ -207,6 +216,27 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
(struct vertex_header *) ((char *) vertex_buffer + (I) * vertex_size)
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
prim.v[0] = VERTEX(i);
setup->point( setup, &prim );
}
break;
case PIPE_PRIM_LINES:
assert(nr % 2 == 0);
for (i = 0; i < nr; i += 2) {
prim.v[0] = VERTEX(i);
prim.v[1] = VERTEX(i + 1);
setup->line( setup, &prim );
}
break;
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i++) {
prim.v[0] = VERTEX(i - 1);
prim.v[1] = VERTEX(i);
setup->line( setup, &prim );
}
break;
case PIPE_PRIM_TRIANGLES:
assert(nr % 3 == 0);
for (i = 0; i < nr; i += 3) {
@ -217,6 +247,58 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
setup->tri( setup, &prim );
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
assert(nr >= 3);
for (i = 2; i < nr; i++) {
prim.v[0] = VERTEX(i - 2);
prim.v[1] = VERTEX(i - 1);
prim.v[2] = VERTEX(i);
calc_det(&prim);
setup->tri( setup, &prim );
}
break;
case PIPE_PRIM_TRIANGLE_FAN:
assert(nr >= 3);
for (i = 2; i < nr; i++) {
prim.v[0] = VERTEX(0);
prim.v[1] = VERTEX(i - 1);
prim.v[2] = VERTEX(i);
calc_det(&prim);
setup->tri( setup, &prim );
}
break;
case PIPE_PRIM_QUADS:
assert(nr % 4 == 0);
for (i = 0; i < nr; i += 4) {
prim.v[0] = VERTEX(i + 0);
prim.v[1] = VERTEX(i + 1);
prim.v[2] = VERTEX(i + 2);
calc_det(&prim);
setup->tri( setup, &prim );
prim.v[0] = VERTEX(i + 0);
prim.v[1] = VERTEX(i + 2);
prim.v[2] = VERTEX(i + 3);
calc_det(&prim);
setup->tri( setup, &prim );
}
break;
case PIPE_PRIM_QUAD_STRIP:
assert(nr >= 4);
for (i = 2; i < nr; i += 2) {
prim.v[0] = VERTEX(i - 2);
prim.v[1] = VERTEX(i);
prim.v[2] = VERTEX(i + 1);
calc_det(&prim);
setup->tri( setup, &prim );
prim.v[0] = VERTEX(i - 2);
prim.v[1] = VERTEX(i + 1);
prim.v[2] = VERTEX(i - 1);
calc_det(&prim);
setup->tri( setup, &prim );
}
break;
case PIPE_PRIM_POLYGON:
/* draw as tri fan */
for (i = 2; i < nr; i++) {

View file

@ -158,6 +158,16 @@ void debug_mask_vprintf(uint32_t uuid,
const char *format,
va_list ap);
#ifdef DEBUG
#define debug_warning(__msg) \
debug_printf("%s:%i:warning: %s\n", __FILE__, __LINE__, (__msg))
#else
#define debug_warning(__msg) \
((void)0)
#endif
#ifdef __cplusplus
}
#endif

View file

@ -88,14 +88,16 @@ FREE( void *ptr )
static INLINE void *
REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
{
void *new_ptr;
if( new_size <= old_size ) {
return old_ptr;
}
new_ptr = MALLOC( new_size );
if( new_ptr ) {
memcpy( new_ptr, old_ptr, old_size );
void *new_ptr = NULL;
if (new_size != 0) {
new_ptr = MALLOC( new_size );
if( new_ptr && old_ptr ) {
memcpy( new_ptr, old_ptr, old_size );
}
}
FREE( old_ptr );
return new_ptr;
}

View file

@ -1576,9 +1576,6 @@ parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
if (err) {
program_error(ctx, Program->Position, "Bad attribute binding");
}
else {
Program->Base.InputsRead |= (1 << *inputReg);
}
return err;
}
@ -2557,6 +2554,11 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
return 1;
}
/* Add attributes to InputsRead only if they are used the program.
* This avoids the handling of unused ATTRIB declarations in the drivers. */
if (*File == PROGRAM_INPUT)
Program->Base.InputsRead |= (1 << *Index);
return 0;
}

View file

@ -172,6 +172,7 @@ STATETRACKER_SOURCES = \
state_tracker/st_atom_texture.c \
state_tracker/st_atom_viewport.c \
state_tracker/st_cb_accum.c \
state_tracker/st_cb_blit.c \
state_tracker/st_cb_bufferobjects.c \
state_tracker/st_cb_clear.c \
state_tracker/st_cb_flush.c \

View file

@ -0,0 +1,125 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Brian Paul
*/
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/texformat.h"
#include "shader/program.h"
#include "shader/prog_parameter.h"
#include "shader/prog_print.h"
#include "st_context.h"
#include "st_program.h"
#include "st_cb_drawpixels.h"
#include "st_cb_blit.h"
#include "st_cb_fbo.h"
#include "util/u_blit.h"
#include "cso_cache/cso_context.h"
void
st_init_blit(struct st_context *st)
{
st->blit = util_create_blit(st->pipe);
}
void
st_destroy_blit(struct st_context *st)
{
util_destroy_blit(st->blit);
st->blit = NULL;
}
static void
st_BlitFramebuffer(GLcontext *ctx,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
struct st_context *st = ctx->st;
struct pipe_context *pipe = st->pipe;
const uint pFilter = ((filter == GL_NEAREST)
? PIPE_TEX_MIPFILTER_NEAREST
: PIPE_TEX_MIPFILTER_LINEAR);
if (mask & GL_COLOR_BUFFER_BIT) {
struct st_renderbuffer *srcRb =
st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
struct st_renderbuffer *dstRb =
st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
struct pipe_surface *srcSurf = srcRb->surface;
struct pipe_surface *dstSurf = dstRb->surface;
srcY0 = srcRb->Base.Height - srcY0;
srcY1 = srcRb->Base.Height - srcY1;
dstY0 = dstRb->Base.Height - dstY0;
dstY1 = dstRb->Base.Height - dstY1;
util_blit_pixels(st->blit,
srcSurf, srcX0, srcY0, srcX1, srcY1,
dstSurf, dstX0, dstY0, dstX1, dstY1,
0.0, pFilter);
}
#if 0
/* XXX is this sufficient? */
st_invalidate_state(ctx, _NEW_COLOR | _NEW_TEXTURE);
#else
/* need to "unset" cso state because we went behind the back of the cso
* tracker. Without unset, the _set_ calls would be no-ops.
*/
cso_unset_blend(st->cso_context);
cso_unset_depth_stencil_alpha(st->cso_context);
cso_unset_rasterizer(st->cso_context);
cso_set_blend(st->cso_context, &st->state.blend);
cso_set_depth_stencil_alpha(st->cso_context, &st->state.depth_stencil);
cso_set_rasterizer(st->cso_context, &st->state.rasterizer);
pipe->bind_fs_state(pipe, st->fp->driver_shader);
pipe->bind_vs_state(pipe, st->vp->driver_shader);
#endif
}
void
st_init_blit_functions(struct dd_function_table *functions)
{
functions->BlitFramebuffer = st_BlitFramebuffer;
}

View file

@ -0,0 +1,46 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef ST_CB_BLIT_H
#define ST_CB_BLIT_H
#include "st_context.h"
extern void
st_init_blit(struct st_context *st);
extern void
st_destroy_blit(struct st_context *st);
extern void
st_init_blit_functions(struct dd_function_table *functions);
#endif /* ST_CB_BLIT_H */

View file

@ -48,6 +48,7 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "pipe/p_winsys.h"
#include "util/u_pack_color.h"
#include "cso_cache/cso_context.h"
@ -56,55 +57,6 @@
#define TEST_DRAW_PASSTHROUGH 0
static GLuint
color_value(enum pipe_format pipeFormat, const GLfloat color[4])
{
GLubyte r, g, b, a;
UNCLAMPED_FLOAT_TO_UBYTE(r, color[0]);
UNCLAMPED_FLOAT_TO_UBYTE(g, color[1]);
UNCLAMPED_FLOAT_TO_UBYTE(b, color[2]);
UNCLAMPED_FLOAT_TO_UBYTE(a, color[3]);
switch (pipeFormat) {
case PIPE_FORMAT_R8G8B8A8_UNORM:
return (r << 24) | (g << 16) | (b << 8) | a;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return (a << 24) | (r << 16) | (g << 8) | b;
case PIPE_FORMAT_B8G8R8A8_UNORM:
return (b << 24) | (g << 16) | (r << 8) | a;
case PIPE_FORMAT_R5G6B5_UNORM:
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
default:
assert(0);
return 0;
}
}
static uint
depth_value(enum pipe_format pipeFormat, GLfloat value)
{
switch (pipeFormat) {
case PIPE_FORMAT_Z16_UNORM:
return (uint) (value * 0xffff);
case PIPE_FORMAT_Z32_UNORM:
/* special-case to avoid overflow */
if (value == 1.0)
return 0xffffffff;
else
return (uint) (value * 0xffffffff);
case PIPE_FORMAT_S8Z24_UNORM:
return (uint) (value * 0xffffff);
case PIPE_FORMAT_Z24S8_UNORM:
return ((uint) (value * 0xffffff)) << 8;
default:
assert(0);
return 0;
}
}
static GLboolean
is_depth_stencil_format(enum pipe_format pipeFormat)
{
@ -405,6 +357,8 @@ clear_with_quad(GLcontext *ctx,
st_invalidate_state(ctx, _NEW_COLOR | _NEW_DEPTH | _NEW_STENCIL);
#else
/* Restore pipe state */
cso_set_blend(st->cso_context, &st->state.blend);
cso_set_depth_stencil_alpha(st->cso_context, &st->state.depth_stencil);
cso_set_rasterizer(st->cso_context, &st->state.rasterizer);
pipe->bind_fs_state(pipe, st->fp->driver_shader);
pipe->bind_vs_state(pipe, st->vp->driver_shader);
@ -518,7 +472,6 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
static void
clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
{
@ -527,10 +480,10 @@ clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE);
}
else {
struct st_renderbuffer *strb = st_renderbuffer(rb);
/* clear whole buffer w/out masking */
uint clearValue = color_value(strb->surface->format, ctx->Color.ClearColor);
struct st_renderbuffer *strb = st_renderbuffer(rb);
uint clearValue;
util_pack_color(ctx->Color.ClearColor, strb->surface->format, &clearValue);
ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
}
}
@ -547,7 +500,7 @@ clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
struct st_renderbuffer *strb = st_renderbuffer(rb);
/* simple clear of whole buffer */
uint clearValue = depth_value(strb->surface->format, ctx->Depth.Clear);
uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
}
}
@ -591,7 +544,7 @@ clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
struct st_renderbuffer *strb = st_renderbuffer(rb);
/* clear whole buffer w/out masking */
GLuint clearValue = depth_value(strb->surface->format, ctx->Depth.Clear);
GLuint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
switch (strb->surface->format) {
case PIPE_FORMAT_S8Z24_UNORM:

View file

@ -36,6 +36,7 @@
#include "st_context.h"
#include "st_cb_accum.h"
#include "st_cb_bufferobjects.h"
#include "st_cb_blit.h"
#include "st_cb_clear.h"
#include "st_cb_drawpixels.h"
#include "st_cb_fbo.h"
@ -100,6 +101,7 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
st_init_atoms( st );
st_init_draw( st );
st_init_generate_mipmap(st);
st_init_blit(st);
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
st->state.sampler_list[i] = &st->state.samplers[i];
@ -151,6 +153,8 @@ static void st_destroy_context_priv( struct st_context *st )
draw_destroy(st->draw);
st_destroy_atoms( st );
st_destroy_draw( st );
st_destroy_generate_mipmap(st);
st_destroy_blit(st);
_vbo_DestroyContext(st->ctx);
@ -217,6 +221,7 @@ void st_init_driver_functions(struct dd_function_table *functions)
st_init_accum_functions(functions);
st_init_bufferobject_functions(functions);
st_init_blit_functions(functions);
st_init_clear_functions(functions);
st_init_drawpixels_functions(functions);
st_init_fbo_functions(functions);

View file

@ -40,6 +40,9 @@ struct draw_context;
struct draw_stage;
struct cso_cache;
struct cso_blend;
struct gen_mipmap_state;
struct blit_state;
#define ST_NEW_MESA 0x1 /* Mesa state has changed */
#define ST_NEW_FRAGMENT_PROGRAM 0x2
@ -146,18 +149,8 @@ struct st_context
struct st_fragment_program *combined_prog;
} bitmap;
/** For gen/render mipmap feature */
struct {
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state depthstencil;
struct pipe_rasterizer_state rasterizer;
void *blend_cso;
void *depthstencil_cso;
void *rasterizer_cso;
struct st_fragment_program *stfp;
struct st_vertex_program *stvp;
} gen_mipmap;
struct gen_mipmap_state *gen_mipmap;
struct blit_state *blit;
struct cso_context *cso_context;
};

View file

@ -143,6 +143,7 @@ void st_init_extensions(struct st_context *st)
ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
ctx->Extensions.EXT_blend_minmax = GL_TRUE;
ctx->Extensions.EXT_blend_subtract = GL_TRUE;
ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
ctx->Extensions.EXT_fog_coord = GL_TRUE;
ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;

View file

@ -37,6 +37,8 @@
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_winsys.h"
#include "util/u_gen_mipmap.h"
#include "cso_cache/cso_cache.h"
#include "cso_cache/cso_context.h"
@ -49,55 +51,6 @@
#include "st_cb_texture.h"
static struct st_fragment_program *
make_tex_fragment_program(GLcontext *ctx)
{
struct st_fragment_program *stfp;
struct gl_program *p;
GLuint ic = 0;
p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!p)
return NULL;
p->NumInstructions = 2;
p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
if (!p->Instructions) {
ctx->Driver.DeleteProgram(ctx, p);
return NULL;
}
_mesa_init_instructions(p->Instructions, p->NumInstructions);
/* TEX result.color, fragment.texcoord[0], texture[0], 2D; */
p->Instructions[ic].Opcode = OPCODE_TEX;
p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
p->Instructions[ic].TexSrcUnit = 0;
p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
/* END; */
p->Instructions[ic++].Opcode = OPCODE_END;
assert(ic == p->NumInstructions);
p->InputsRead = FRAG_BIT_TEX0;
p->OutputsWritten = (1 << FRAG_RESULT_COLR);
stfp = (struct st_fragment_program *) p;
st_translate_fragment_program(ctx->st, stfp, NULL);
return stfp;
}
/**
* one-time init for generate mipmap
* XXX Note: there may be other times we need no-op/simple state like this.
@ -106,117 +59,18 @@ make_tex_fragment_program(GLcontext *ctx)
void
st_init_generate_mipmap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct pipe_blend_state blend;
struct pipe_rasterizer_state rasterizer;
struct pipe_depth_stencil_alpha_state depthstencil;
/* we don't use blending, but need to set valid values */
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask = PIPE_MASK_RGBA;
st->gen_mipmap.blend = blend;
st->gen_mipmap.blend_cso = pipe->create_blend_state(pipe, &blend);
memset(&depthstencil, 0, sizeof(depthstencil));
st->gen_mipmap.depthstencil_cso = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
/* Note: we're assuming zero is valid for all non-specified fields */
memset(&rasterizer, 0, sizeof(rasterizer));
rasterizer.front_winding = PIPE_WINDING_CW;
rasterizer.cull_mode = PIPE_WINDING_NONE;
st->gen_mipmap.rasterizer_cso = pipe->create_rasterizer_state(pipe, &rasterizer);
st->gen_mipmap.stfp = make_tex_fragment_program(st->ctx);
st->gen_mipmap.stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
st->gen_mipmap = util_create_gen_mipmap(st->pipe);
}
void
st_destroy_generate_mipmpap(struct st_context *st)
st_destroy_generate_mipmap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
pipe->delete_blend_state(pipe, st->gen_mipmap.blend_cso);
pipe->delete_depth_stencil_alpha_state(pipe, st->gen_mipmap.depthstencil_cso);
pipe->delete_rasterizer_state(pipe, st->gen_mipmap.rasterizer_cso);
/* XXX free stfp, stvp */
util_destroy_gen_mipmap(st->gen_mipmap);
st->gen_mipmap = NULL;
}
static void
simple_viewport(struct pipe_context *pipe, uint width, uint height)
{
struct pipe_viewport_state vp;
vp.scale[0] = 0.5 * width;
vp.scale[1] = -0.5 * height;
vp.scale[2] = 1.0;
vp.scale[3] = 1.0;
vp.translate[0] = 0.5 * width;
vp.translate[1] = 0.5 * height;
vp.translate[2] = 0.0;
vp.translate[3] = 0.0;
pipe->set_viewport_state(pipe, &vp);
}
/*
* Draw simple [-1,1]x[-1,1] quad
*/
static void
draw_quad(GLcontext *ctx)
{
GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
GLuint i;
GLfloat sLeft = 0.0, sRight = 1.0;
GLfloat tTop = 1.0, tBot = 0.0;
GLfloat x0 = -1.0, x1 = 1.0;
GLfloat y0 = -1.0, y1 = 1.0;
/* upper-left */
verts[0][0][0] = x0; /* attr[0].x */
verts[0][0][1] = y0; /* attr[0].y */
verts[0][1][0] = sLeft; /* attr[1].s */
verts[0][1][1] = tTop; /* attr[1].t */
/* upper-right */
verts[1][0][0] = x1;
verts[1][0][1] = y0;
verts[1][1][0] = sRight;
verts[1][1][1] = tTop;
/* lower-right */
verts[2][0][0] = x1;
verts[2][0][1] = y1;
verts[2][1][0] = sRight;
verts[2][1][1] = tBot;
/* lower-left */
verts[3][0][0] = x0;
verts[3][0][1] = y1;
verts[3][1][0] = sLeft;
verts[3][1][1] = tBot;
/* same for all verts: */
for (i = 0; i < 4; i++) {
verts[i][0][2] = 0.0; /*Z*/
verts[i][0][3] = 1.0; /*W*/
verts[i][1][2] = 0.0; /*R*/
verts[i][1][3] = 1.0; /*Q*/
}
st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2, GL_TRUE);
}
/**
* Generate mipmap levels using hardware rendering.
* \return TRUE if successful, FALSE if not possible
@ -229,12 +83,7 @@ st_render_mipmap(struct st_context *st,
{
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
struct pipe_sampler_state sampler;
void *sampler_cso;
const uint face = _mesa_tex_target_to_face(target), zslice = 0;
/*const uint first_level_save = pt->first_level;*/
uint dstLevel;
const uint face = _mesa_tex_target_to_face(target);
assert(target != GL_TEXTURE_3D); /* not done yet */
@ -243,66 +92,7 @@ st_render_mipmap(struct st_context *st,
return FALSE;
}
/* init framebuffer state */
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
/* sampler state */
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.normalized_coords = 1;
/* bind state */
cso_set_blend(st->cso_context, &st->gen_mipmap.blend);
cso_set_depth_stencil_alpha(st->cso_context, &st->gen_mipmap.depthstencil);
cso_set_rasterizer(st->cso_context, &st->gen_mipmap.rasterizer);
/* bind shaders */
pipe->bind_fs_state(pipe, st->gen_mipmap.stfp->driver_shader);
pipe->bind_vs_state(pipe, st->gen_mipmap.stvp->driver_shader);
/*
* XXX for small mipmap levels, it may be faster to use the software
* fallback path...
*/
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
/*
* Setup framebuffer / dest surface
*/
fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
pipe->set_framebuffer_state(pipe, &fb);
/*
* Setup sampler state
*/
sampler.min_lod = sampler.max_lod = srcLevel;
sampler_cso = pipe->create_sampler_state(pipe, &sampler);
pipe->bind_sampler_states(pipe, 1, &sampler_cso);
simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
/*
* Setup src texture, override pt->first_level so we sample from
* the right mipmap level.
*/
/*pt->first_level = srcLevel;*/
pipe->set_sampler_textures(pipe, 1, &pt);
draw_quad(st->ctx);
pipe->delete_sampler_state(pipe, sampler_cso);
}
/* restore first_level */
/*pt->first_level = first_level_save;*/
util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel);
/* restore pipe state */
#if 0

View file

@ -35,7 +35,7 @@ st_init_generate_mipmap(struct st_context *st);
extern void
st_destroy_generate_mipmpap(struct st_context *st);
st_destroy_generate_mipmap(struct st_context *st);
extern void

View file

@ -348,8 +348,6 @@ static GLboolean build_vertex_emit( struct x86_program *p )
struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
GLubyte *fixup, *label;
x86_init_func(&p->func);
/* Push a few regs?
*/
x86_push(&p->func, countEBP);
@ -641,7 +639,7 @@ void _tnl_generate_sse_emit( GLcontext *ctx )
p.ctx = ctx;
p.inputs_safe = 0; /* for now */
p.outputs_safe = 1; /* for now */
p.outputs_safe = 0; /* for now */
p.have_sse2 = cpu_has_xmm2;
p.identity = x86_make_reg(file_XMM, 6);
p.chan0 = x86_make_reg(file_XMM, 7);

View file

@ -633,7 +633,7 @@ void vf_generate_sse_emit( struct vertex_fetch *vf )
p.vf = vf;
p.inputs_safe = 0; /* for now */
p.outputs_safe = 1; /* for now */
p.outputs_safe = 0; /* for now */
p.have_sse2 = cpu_has_xmm2;
p.identity = x86_make_reg(file_XMM, 6);
p.chan0 = x86_make_reg(file_XMM, 7);