tests/graw: Add a bunch of tests.

These were rotting in an internal branch, but contain nothing confidential,
and would be much more useful if kept up-to-date with latest gallium
interface changes.

Several authors including Keith Whitwell, Zack Rusin, and Brian Paul.
This commit is contained in:
José Fonseca 2012-02-22 15:22:31 +00:00
parent 0df14f9a55
commit d35d3d612a
10 changed files with 1795 additions and 373 deletions

View file

@ -16,15 +16,21 @@ if env['platform'] == 'freebsd8':
progs = [
'clear',
'tri',
'tri-instanced',
'quad-tex',
'fs-fragcoord',
'fs-frontface',
'fs-test',
'vs-test',
'fs-write-z',
'gs-test',
'shader-leak',
'tri-gs',
'occlusion-query',
'quad-sample',
'quad-tex',
'shader-leak',
'tex-srgb',
'tex-swizzle',
'tri',
'tri-gs',
'tri-instanced',
'vs-test',
]
for name in progs:

View file

@ -0,0 +1,259 @@
/* Test the TGSI_SEMANTIC_POSITION fragment shader input.
* Plus properties for upper-left vs. lower-left origin and
* center integer vs. half-integer;
*/
#include <stdio.h>
#include "graw_util.h"
static int width = 300;
static int height = 300;
static struct graw_info info;
struct vertex {
float position[4];
float color[4];
};
/* Note: the upper-left vertex is pushed to the left a bit to
* make sure we can spot upside-down rendering.
*/
static struct vertex vertices[] =
{
{
{-0.95, -0.95, 0.5, 1.0 },
{ 0, 0, 0, 1 }
},
{
{ 0.85, -0.95, 0.5, 1.0 },
{ 0, 0, 0, 1 }
},
{
{ 0.95, 0.95, 0.5, 1.0 },
{ 0, 0, 0, 1 }
},
{
{-0.95, 0.95, 0.5, 1.0 },
{ 0, 0, 0, 1 }
}
};
#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0]))
static void
set_vertices(void)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void
set_vertex_shader(void)
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: MOV OUT[1], IN[1]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void
set_fragment_shader(int mode)
{
void *handle;
const char *origin_upper_left_text =
"FRAG\n"
"PROPERTY FS_COORD_ORIGIN UPPER_LEFT\n" /* upper-left = black corner */
"DCL IN[0], POSITION, LINEAR\n"
"DCL OUT[0], COLOR\n"
"DCL TEMP[0]\n"
"IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 }\n"
"IMM FLT32 { 0.0, 300.0, 0.0, 0.0 }\n"
" 0: MOV TEMP[0], IN[0] \n"
" 1: MOV TEMP[0].zw, IMM[1].xxxx \n"
" 2: MUL OUT[0], TEMP[0], IMM[0] \n"
" 3: END\n";
const char *origin_lower_left_text =
"FRAG\n"
"PROPERTY FS_COORD_ORIGIN LOWER_LEFT\n" /* lower-left = black corner */
"DCL IN[0], POSITION, LINEAR\n"
"DCL OUT[0], COLOR\n"
"DCL TEMP[0]\n"
"IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 }\n"
"IMM FLT32 { 0.0, 300.0, 0.0, 0.0 }\n"
" 0: MOV TEMP[0], IN[0] \n"
" 1: MOV TEMP[0].zw, IMM[1].xxxx \n"
" 2: MUL OUT[0], TEMP[0], IMM[0] \n"
" 3: END\n";
/* Test fragcoord center integer vs. half integer */
const char *center_integer_text =
"FRAG\n"
"PROPERTY FS_COORD_PIXEL_CENTER INTEGER \n" /* pixels are black */
"DCL IN[0], POSITION, LINEAR \n"
"DCL OUT[0], COLOR \n"
"DCL TEMP[0] \n"
"IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 } \n"
"IMM FLT32 { 0.0, 300.0, 0.0, 0.0 } \n"
"0: FRC TEMP[0], IN[0] \n"
"1: MOV TEMP[0].zw, IMM[1].xxxx \n"
"2: MOV OUT[0], TEMP[0] \n"
"3: END \n";
const char *center_half_integer_text =
"FRAG\n"
"PROPERTY FS_COORD_PIXEL_CENTER HALF_INTEGER \n" /* pixels are olive colored */
"DCL IN[0], POSITION, LINEAR \n"
"DCL OUT[0], COLOR \n"
"DCL TEMP[0] \n"
"IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 } \n"
"IMM FLT32 { 0.0, 300.0, 0.0, 0.0 } \n"
"0: FRC TEMP[0], IN[0] \n"
"1: MOV TEMP[0].zw, IMM[1].xxxx \n"
"2: MOV OUT[0], TEMP[0] \n"
"3: END \n";
const char *text;
if (mode == 0)
text = origin_upper_left_text;
else if (mode == 1)
text = origin_lower_left_text;
else if (mode == 2)
text = center_integer_text;
else
text = center_half_integer_text;
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
static void
draw(void)
{
union pipe_color_union clear_color;
clear_color.f[0] = 0.25;
clear_color.f[1] = 0.25;
clear_color.f[2] = 0.25;
clear_color.f[3] = 1.0;
info.ctx->clear(info.ctx,
PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
&clear_color, 1.0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
info.ctx->flush(info.ctx, NULL);
#if 0
/* At the moment, libgraw leaks out/makes available some of the
* symbols from gallium/auxiliary, including these debug helpers.
* Will eventually want to bless some of these paths, and lock the
* others down so they aren't accessible from test programs.
*
* This currently just happens to work on debug builds - a release
* build will probably fail to link here:
*/
debug_dump_surface_bmp(info.ctx, "result.bmp", surf);
#endif
graw_util_flush_front(&info);
}
#if 0
static void
resize(int w, int h)
{
width = w;
height = h;
set_viewport(0, 0, width, height, 30, 1000);
}
#endif
static void
init(int mode)
{
if (!graw_util_create_window(&info, width, height, 1, TRUE))
exit(1);
graw_util_default_state(&info, TRUE);
graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0);
set_vertices();
set_vertex_shader();
set_fragment_shader(mode);
}
int
main(int argc, char *argv[])
{
int mode = argc > 1 ? atoi(argv[1]) : 0;
switch (mode) {
default:
case 0:
printf("frag coord origin upper-left (lower-left = black)\n");
break;
case 1:
printf("frag coord origin lower-left (upper-left = black)\n");
break;
case 2:
printf("frag coord center integer (all pixels black)\n");
break;
case 3:
printf("frag coord center half-integer (all pixels olive color)\n");
break;
}
init(mode);
graw_set_display_func(draw);
/*graw_set_reshape_func(resize);*/
graw_main_loop();
return 0;
}

View file

@ -0,0 +1,206 @@
/* Test the TGSI_SEMANTIC_FACE fragment shader input.
*/
#include <stdio.h>
#include "graw_util.h"
static int width = 300;
static int height = 300;
static struct graw_info info;
struct vertex {
float position[4];
float color[4];
};
#define z0 0.2
#define z01 0.5
#define z1 0.4
static struct vertex vertices[] =
{
/* left quad: clock-wise, front-facing, red */
{
{-0.8, -0.9, z0, 1.0 },
{ 0, 0, 0, 1 }
},
{
{ -0.2, -0.9, z0, 1.0 },
{ 0, 0, 0, 1 }
},
{
{ 0.2, 0.9, z01, 1.0 },
{ 0, 0, 0, 1 }
},
{
{-0.9, 0.9, z01, 1.0 },
{ 0, 0, 0, 1 }
},
/* right quad : counter-clock-wise, back-facing, green */
{
{ 0.2, -0.9, z1, 1.0 },
{ 1, 1, 1, -1 }
},
{
{ -0.2, 0.8, z1, 1.0 },
{ 1, 1, 1, -1 }
},
{
{ 0.9, 0.8, z1, 1.0 },
{ 1, 1, 1, -1 }
},
{
{ 0.8, -0.9, z1, 1.0 },
{ 1, 1, 1, -1 }
},
};
#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0]))
static void
set_vertices(void)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void
set_vertex_shader(void)
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: MOV OUT[1], IN[1]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void
set_fragment_shader(void)
{
void *handle;
const char *text =
"FRAG\n"
"DCL IN[0], FACE, CONSTANT\n"
"DCL IN[1], GENERIC, CONSTANT\n"
"DCL OUT[0], COLOR\n"
"DCL TEMP[0]\n"
"IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }\n"
"IMM FLT32 { 0.0, 1.0, 0.0, 0.0 }\n"
"IMM FLT32 { 0.5, 0.6, 0.0, 0.0 }\n"
" 0: SGT TEMP[0].x, IN[0].xxxx, IMM[1].xxxx\n" /* TMP[0].x = IN[0].x > 0.0 */
" 1: IF TEMP[0].xxxx :4\n"
" 2: MOV OUT[0], IMM[0]\n" /* front-facing: red */
" 3: ELSE :5\n"
" 4: MOV OUT[0], IMM[1]\n" /* back-facing: green */
" 5: ENDIF\n"
" 6: END\n";
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
static void
draw(void)
{
union pipe_color_union clear_color;
clear_color.f[0] = 0.25;
clear_color.f[1] = 0.25;
clear_color.f[2] = 0.25;
clear_color.f[3] = 1.00;
info.ctx->clear(info.ctx,
PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
&clear_color, 1.0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
info.ctx->flush(info.ctx, NULL);
graw_util_flush_front(&info);
}
#if 0
static void
resize(int w, int h)
{
width = w;
height = h;
set_viewport(0, 0, width, height, 30, 1000);
}
#endif
static void
init(void)
{
if (!graw_util_create_window(&info, width, height, 1, TRUE))
exit(1);
graw_util_default_state(&info, TRUE);
graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0);
set_vertices();
set_vertex_shader();
set_fragment_shader();
}
int
main(int argc, char *argv[])
{
init();
printf("Left quad: clock-wise, front-facing, red\n");
printf("Right quad: counter clock-wise, back-facing, green\n");
graw_set_display_func(draw);
/*graw_set_reshape_func(resize);*/
graw_main_loop();
return 0;
}

View file

@ -0,0 +1,222 @@
/* Test the writing Z in fragment shader.
* The red quad should be entirely in front of the blue quad even
* though the overlap and intersect in Z.
*/
#include <stdio.h>
#include "graw_util.h"
static int width = 300;
static int height = 300;
static struct graw_info info;
struct vertex {
float position[4];
float color[4];
};
#define z0 0.2
#define z01 0.5
#define z1 0.4
static struct vertex vertices[] =
{
/* left quad: clock-wise, front-facing, red */
{
{-0.8, -0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
},
{
{ -0.2, -0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
},
{
{ 0.2, 0.9, z01, 1.0 },
{ 1, 0, 0, 1 }
},
{
{-0.9, 0.9, z01, 1.0 },
{ 1, 0, 0, 1 }
},
/* right quad : counter-clock-wise, back-facing, green */
{
{ 0.2, -0.9, z1, 1.0 },
{ 0, 0, 1, -1 }
},
{
{ -0.2, 0.8, z1, 1.0 },
{ 0, 0, 1, -1 }
},
{
{ 0.9, 0.8, z1, 1.0 },
{ 0, 0, 1, -1 }
},
{
{ 0.8, -0.9, z1, 1.0 },
{ 0, 0, 1, -1 }
},
};
#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0]))
static void
set_vertices(void)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void
set_vertex_shader(void)
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: MOV OUT[1], IN[1]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void
set_fragment_shader(void)
{
void *handle;
const char *text =
"FRAG\n"
"DCL IN[0], GENERIC, CONSTANT\n"
"DCL OUT[0], COLOR\n"
"DCL OUT[1], POSITION\n"
"DCL TEMP[0]\n"
"IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }\n"
"IMM FLT32 { 0.0, 1.0, 0.0, 0.0 }\n"
"IMM FLT32 { 0.5, 0.4, 0.0, 0.0 }\n"
" 0: MOV OUT[0], IN[0]\n" /* front-facing: red */
" 1: IF IN[0].xxxx :3\n"
" 2: MOV OUT[1].z, IMM[2].yyyy\n" /* red: Z = 0.4 */
" 3: ELSE :5\n"
" 4: MOV OUT[1].z, IMM[2].xxxx\n" /* blue: Z = 0.5 */
" 5: ENDIF\n"
" 6: END\n";
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
static void
draw(void)
{
union pipe_color_union clear_color;
clear_color.f[0] = 0.25;
clear_color.f[1] = 0.25;
clear_color.f[2] = 0.25;
clear_color.f[3] = 1.00;
info.ctx->clear(info.ctx,
PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
&clear_color, 1.0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
info.ctx->flush(info.ctx, NULL);
#if 0
/* At the moment, libgraw leaks out/makes available some of the
* symbols from gallium/auxiliary, including these debug helpers.
* Will eventually want to bless some of these paths, and lock the
* others down so they aren't accessible from test programs.
*
* This currently just happens to work on debug builds - a release
* build will probably fail to link here:
*/
debug_dump_surface_bmp(info.ctx, "result.bmp", surf);
#endif
graw_util_flush_front(&info);
}
#if 0
static void
resize(int w, int h)
{
width = w;
height = h;
graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0);
}
#endif
static void
init(void)
{
if (!graw_util_create_window(&info, width, height, 1, TRUE))
exit(1);
graw_util_default_state(&info, TRUE);
graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0);
set_vertices();
set_vertex_shader();
set_fragment_shader();
}
int
main(int argc, char *argv[])
{
init();
printf("The red quad should be entirely in front of the blue quad.\n");
graw_set_display_func(draw);
/*graw_set_reshape_func(resize);*/
graw_main_loop();
return 0;
}

View file

@ -0,0 +1,329 @@
#include "state_tracker/graw.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "util/u_box.h"
#include "util/u_debug.h"
#include "util/u_draw_quad.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
struct graw_info
{
struct pipe_screen *screen;
struct pipe_context *ctx;
struct pipe_resource *color_buf[PIPE_MAX_COLOR_BUFS], *zs_buf;
struct pipe_surface *color_surf[PIPE_MAX_COLOR_BUFS], *zs_surf;
void *window;
};
static INLINE boolean
graw_util_create_window(struct graw_info *info,
int width, int height,
int num_cbufs, bool zstencil_buf)
{
static const enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_NONE
};
enum pipe_format format;
struct pipe_resource resource_temp;
struct pipe_surface surface_temp;
int i;
memset(info, 0, sizeof(*info));
/* It's hard to say whether window or screen should be created
* first. Different environments would prefer one or the other.
*
* Also, no easy way of querying supported formats if the screen
* cannot be created first.
*/
for (i = 0; info->window == NULL && formats[i] != PIPE_FORMAT_NONE; i++) {
info->screen = graw_create_window_and_screen(0, 0, width, height,
formats[i],
&info->window);
format = formats[i];
}
if (!info->screen || !info->window) {
debug_printf("graw: Failed to create screen/window\n");
return FALSE;
}
info->ctx = info->screen->context_create(info->screen, NULL);
if (info->ctx == NULL) {
debug_printf("graw: Failed to create context\n");
return FALSE;
}
for (i = 0; i < num_cbufs; i++) {
/* create color texture */
resource_temp.target = PIPE_TEXTURE_2D;
resource_temp.format = format;
resource_temp.width0 = width;
resource_temp.height0 = height;
resource_temp.depth0 = 1;
resource_temp.array_size = 1;
resource_temp.last_level = 0;
resource_temp.nr_samples = 1;
resource_temp.bind = (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET);
info->color_buf[i] = info->screen->resource_create(info->screen,
&resource_temp);
if (info->color_buf[i] == NULL) {
debug_printf("graw: Failed to create color texture\n");
return FALSE;
}
/* create color surface */
surface_temp.format = resource_temp.format;
surface_temp.usage = PIPE_BIND_RENDER_TARGET;
surface_temp.u.tex.level = 0;
surface_temp.u.tex.first_layer = 0;
surface_temp.u.tex.last_layer = 0;
info->color_surf[i] = info->ctx->create_surface(info->ctx,
info->color_buf[i],
&surface_temp);
if (info->color_surf[i] == NULL) {
debug_printf("graw: Failed to get color surface\n");
return FALSE;
}
}
/* create Z texture (XXX try other Z/S formats if needed) */
resource_temp.target = PIPE_TEXTURE_2D;
resource_temp.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
resource_temp.width0 = width;
resource_temp.height0 = height;
resource_temp.depth0 = 1;
resource_temp.array_size = 1;
resource_temp.last_level = 0;
resource_temp.nr_samples = 1;
resource_temp.bind = PIPE_BIND_DEPTH_STENCIL;
info->zs_buf = info->screen->resource_create(info->screen, &resource_temp);
if (!info->zs_buf) {
debug_printf("graw: Failed to create Z texture\n");
return FALSE;
}
/* create z surface */
surface_temp.format = resource_temp.format;
surface_temp.usage = PIPE_BIND_DEPTH_STENCIL;
surface_temp.u.tex.level = 0;
surface_temp.u.tex.first_layer = 0;
surface_temp.u.tex.last_layer = 0;
info->zs_surf = info->ctx->create_surface(info->ctx,
info->zs_buf,
&surface_temp);
if (info->zs_surf == NULL) {
debug_printf("graw: Failed to get Z surface\n");
return FALSE;
}
{
struct pipe_framebuffer_state fb;
memset(&fb, 0, sizeof fb);
fb.nr_cbufs = num_cbufs;
fb.width = width;
fb.height = height;
for (i = 0; i < num_cbufs; i++)
fb.cbufs[i] = info->color_surf[i];
fb.zsbuf = info->zs_surf;
info->ctx->set_framebuffer_state(info->ctx, &fb);
}
return TRUE;
}
static INLINE void
graw_util_default_state(struct graw_info *info, boolean depth_test)
{
{
struct pipe_blend_state blend;
void *handle;
memset(&blend, 0, sizeof blend);
blend.rt[0].colormask = PIPE_MASK_RGBA;
handle = info->ctx->create_blend_state(info->ctx, &blend);
info->ctx->bind_blend_state(info->ctx, handle);
}
{
struct pipe_depth_stencil_alpha_state depthStencilAlpha;
void *handle;
memset(&depthStencilAlpha, 0, sizeof depthStencilAlpha);
depthStencilAlpha.depth.enabled = depth_test;
depthStencilAlpha.depth.writemask = 1;
depthStencilAlpha.depth.func = PIPE_FUNC_LESS;
handle = info->ctx->create_depth_stencil_alpha_state(info->ctx,
&depthStencilAlpha);
info->ctx->bind_depth_stencil_alpha_state(info->ctx, handle);
}
{
struct pipe_rasterizer_state rasterizer;
void *handle;
memset(&rasterizer, 0, sizeof rasterizer);
rasterizer.cull_face = PIPE_FACE_NONE;
rasterizer.gl_rasterization_rules = 1;
handle = info->ctx->create_rasterizer_state(info->ctx, &rasterizer);
info->ctx->bind_rasterizer_state(info->ctx, handle);
}
}
static INLINE void
graw_util_viewport(struct graw_info *info,
float x, float y,
float width, float height,
float near, float far)
{
float z = near;
float half_width = width / 2.0f;
float half_height = height / 2.0f;
float half_depth = (far - near) / 2.0f;
struct pipe_viewport_state vp;
vp.scale[0] = half_width;
vp.scale[1] = half_height;
vp.scale[2] = half_depth;
vp.scale[3] = 1.0f;
vp.translate[0] = half_width + x;
vp.translate[1] = half_height + y;
vp.translate[2] = half_depth + z;
vp.translate[3] = 0.0f;
info->ctx->set_viewport_state(info->ctx, &vp);
}
static INLINE void
graw_util_flush_front(const struct graw_info *info)
{
info->screen->flush_frontbuffer(info->screen, info->color_buf[0],
0, 0, info->window);
}
static INLINE struct pipe_resource *
graw_util_create_tex2d(const struct graw_info *info,
int width, int height, enum pipe_format format,
const void *data)
{
const int row_stride = width * util_format_get_blocksize(format);
const int image_bytes = row_stride * height;
struct pipe_resource temp, *tex;
struct pipe_box box;
temp.target = PIPE_TEXTURE_2D;
temp.format = PIPE_FORMAT_B8G8R8A8_UNORM;
temp.width0 = width;
temp.height0 = height;
temp.depth0 = 1;
temp.last_level = 0;
temp.array_size = 1;
temp.nr_samples = 1;
temp.bind = PIPE_BIND_SAMPLER_VIEW;
tex = info->screen->resource_create(info->screen, &temp);
if (!tex) {
debug_printf("graw: failed to create texture\n");
return NULL;
}
u_box_2d(0, 0, width, height, &box);
info->ctx->transfer_inline_write(info->ctx,
tex,
0,
PIPE_TRANSFER_WRITE,
&box,
data,
row_stride,
image_bytes);
/* Possibly read back & compare against original data:
*/
#if 0
{
struct pipe_transfer *t;
uint32_t *ptr;
t = pipe_get_transfer(info->ctx, samptex,
0, 0, /* level, layer */
PIPE_TRANSFER_READ,
0, 0, SIZE, SIZE); /* x, y, width, height */
ptr = info->ctx->transfer_map(info->ctx, t);
if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
assert(0);
exit(9);
}
info->ctx->transfer_unmap(info->ctx, t);
info->ctx->transfer_destroy(info->ctx, t);
}
#endif
return tex;
}
static INLINE void *
graw_util_create_simple_sampler(const struct graw_info *info,
unsigned wrap_mode,
unsigned img_filter)
{
struct pipe_sampler_state sampler_desc;
void *sampler;
memset(&sampler_desc, 0, sizeof sampler_desc);
sampler_desc.wrap_s =
sampler_desc.wrap_t =
sampler_desc.wrap_r = wrap_mode;
sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler_desc.min_img_filter =
sampler_desc.mag_img_filter = img_filter;
sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler_desc.compare_func = 0;
sampler_desc.normalized_coords = 1;
sampler_desc.max_anisotropy = 0;
sampler = info->ctx->create_sampler_state(info->ctx, &sampler_desc);
return sampler;
}
static INLINE struct pipe_sampler_view *
graw_util_create_simple_sampler_view(const struct graw_info *info,
struct pipe_resource *texture)
{
struct pipe_sampler_view sv_temp;
struct pipe_sampler_view *sv;
memset(&sv_temp, 0, sizeof(sv_temp));
sv_temp.format = texture->format;
sv_temp.texture = texture;
sv_temp.swizzle_r = PIPE_SWIZZLE_RED;
sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN;
sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE;
sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA;
sv = info->ctx->create_sampler_view(info->ctx, texture, &sv_temp);
return sv;
}

View file

@ -0,0 +1,242 @@
/* Test gallium occlusion queries.
*/
#include <stdio.h>
#include "graw_util.h"
static int width = 300;
static int height = 300;
/* expected results of occlusion test (depndsd on window size) */
static int expected1 = (int) ((300 * 0.9) * (300 * 0.9));
static int expected2 = 420;
static struct graw_info info;
struct vertex {
float position[4];
float color[4];
};
#define z0 0.2
#define z1 0.6
static struct vertex obj1_vertices[4] =
{
{
{-0.9, -0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
},
{
{ 0.9, -0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
},
{
{ 0.9, 0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
},
{
{-0.9, 0.9, z0, 1.0 },
{ 1, 0, 0, 1 }
}
};
static struct vertex obj2_vertices[4] =
{
{
{ -0.2, -0.2, z1, 1.0 },
{ 0, 0, 1, 1 }
},
{
{ 0.95, -0.2, z1, 1.0 },
{ 0, 0, 1, 1 }
},
{
{ 0.95, 0.2, z1, 1.0 },
{ 0, 0, 1, 1 }
},
{
{ -0.2, 0.2, z1, 1.0 },
{ 0, 0, 1, 1 }
},
};
#define NUM_VERTS 4
static void
set_vertices(struct vertex *vertices, unsigned bytes)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
bytes,
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void
set_vertex_shader(struct graw_info *info)
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: MOV OUT[1], IN[1]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info->ctx, text);
if (!handle) {
debug_printf("Failed to parse vertex shader\n");
return;
}
info->ctx->bind_vs_state(info->ctx, handle);
}
static void
set_fragment_shader(struct graw_info *info)
{
void *handle;
const char *text =
"FRAG\n"
"DCL IN[0], GENERIC, LINEAR\n"
"DCL OUT[0], COLOR\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: END\n";
handle = graw_parse_fragment_shader(info->ctx, text);
if (!handle) {
debug_printf("Failed to parse fragment shader\n");
return;
}
info->ctx->bind_fs_state(info->ctx, handle);
}
static void
draw(void)
{
int expected1_min = (int) (expected1 * 0.95);
int expected1_max = (int) (expected1 * 1.05);
int expected2_min = (int) (expected2 * 0.95);
int expected2_max = (int) (expected2 * 1.05);
union pipe_color_union clear_color;
struct pipe_query *q1, *q2;
uint64_t res1, res2;
clear_color.f[0] = 0.25;
clear_color.f[1] = 0.25;
clear_color.f[2] = 0.25;
clear_color.f[3] = 1.00;
info.ctx->clear(info.ctx,
PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
&clear_color, 1.0, 0);
q1 = info.ctx->create_query(info.ctx, PIPE_QUERY_OCCLUSION_COUNTER);
q2 = info.ctx->create_query(info.ctx, PIPE_QUERY_OCCLUSION_COUNTER);
/* draw first, large object */
set_vertices(obj1_vertices, sizeof(obj1_vertices));
info.ctx->begin_query(info.ctx, q1);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
info.ctx->end_query(info.ctx, q1);
/* draw second, small object behind first object */
set_vertices(obj2_vertices, sizeof(obj2_vertices));
info.ctx->begin_query(info.ctx, q2);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
info.ctx->end_query(info.ctx, q2);
info.ctx->get_query_result(info.ctx, q1, TRUE, &res1);
info.ctx->get_query_result(info.ctx, q2, TRUE, &res2);
printf("result1 = %lu result2 = %lu\n", res1, res2);
if (res1 < expected1_min || res1 > expected1_max)
printf(" Failure: result1 should be near %d\n", expected1);
if (res2 < expected2_min || res2 > expected2_max)
printf(" Failure: result2 should be near %d\n", expected2);
info.ctx->flush(info.ctx, NULL);
graw_util_flush_front(&info);
info.ctx->destroy_query(info.ctx, q1);
info.ctx->destroy_query(info.ctx, q2);
}
#if 0
static void
resize(int w, int h)
{
width = w;
height = h;
graw_util_viewport(&info, 0, 0, width, height, 30, 1000);
}
#endif
static void
init(void)
{
if (!graw_util_create_window(&info, width, height, 1, TRUE))
exit(1);
graw_util_default_state(&info, TRUE);
graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0);
set_vertex_shader(&info);
set_fragment_shader(&info);
}
int
main(int argc, char *argv[])
{
init();
printf("The red quad should mostly occlude the blue quad.\n");
graw_set_display_func(draw);
/*graw_set_reshape_func(resize);*/
graw_main_loop();
return 0;
}

View file

@ -2,36 +2,17 @@
* any utility code, just the graw interface and gallium.
*/
#include <stdio.h>
#include "state_tracker/graw.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_memory.h" /* Offset() */
#include "util/u_draw_quad.h"
#include "util/u_box.h"
enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_NONE
};
#include "graw_util.h"
static const int WIDTH = 300;
static const int HEIGHT = 300;
static struct pipe_screen *screen = NULL;
static struct pipe_context *ctx = NULL;
static struct pipe_resource *rttex = NULL;
static struct pipe_resource *samptex = NULL;
static struct pipe_surface *surf = NULL;
static struct graw_info info;
static struct pipe_resource *texture = NULL;
static struct pipe_sampler_view *sv = NULL;
static void *sampler = NULL;
static void *window = NULL;
struct vertex {
float position[4];
@ -56,29 +37,6 @@ static struct vertex vertices[] =
static void set_viewport( float x, float y,
float width, float height,
float near, float far)
{
float z = far;
float half_width = (float)width / 2.0f;
float half_height = (float)height / 2.0f;
float half_depth = ((float)far - (float)near) / 2.0f;
struct pipe_viewport_state vp;
vp.scale[0] = half_width;
vp.scale[1] = half_height;
vp.scale[2] = half_depth;
vp.scale[3] = 1.0f;
vp.translate[0] = half_width + x;
vp.translate[1] = half_height + y;
vp.translate[2] = half_depth + z;
vp.translate[3] = 0.0f;
ctx->set_viewport_state( ctx, &vp );
}
static void set_vertices( void )
{
struct pipe_vertex_element ve[2];
@ -92,18 +50,18 @@ static void set_vertices( void )
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = ctx->create_vertex_elements_state(ctx, 2, ve);
ctx->bind_vertex_elements_state(ctx, handle);
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof( struct vertex );
vbuf.buffer_offset = 0;
vbuf.buffer = screen->user_buffer_create(screen,
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
ctx->set_vertex_buffers(ctx, 1, &vbuf);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void set_vertex_shader( void )
@ -119,8 +77,8 @@ static void set_vertex_shader( void )
" 1: MOV OUT[0], IN[0]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(ctx, text);
ctx->bind_vs_state(ctx, handle);
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void set_fragment_shader( void )
@ -136,8 +94,8 @@ static void set_fragment_shader( void )
" 1: MOV OUT[0], TEMP[0]\n"
" 2: END\n";
handle = graw_parse_fragment_shader(ctx, text);
ctx->bind_fs_state(ctx, handle);
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
@ -145,23 +103,20 @@ static void draw( void )
{
union pipe_color_union clear_color = { {.5,.5,.5,1} };
ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
ctx->flush(ctx, NULL);
info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
info.ctx->flush(info.ctx, NULL);
graw_save_surface_to_file(ctx, surf, NULL);
graw_save_surface_to_file(info.ctx, info.color_surf[0], NULL);
screen->flush_frontbuffer(screen, rttex, 0, 0, window);
graw_util_flush_front(&info);
}
#define SIZE 16
static void init_tex( void )
{
struct pipe_sampler_view sv_template;
struct pipe_sampler_state sampler_desc;
struct pipe_resource templat;
struct pipe_box box;
ubyte tex2d[SIZE][SIZE][4];
int s, t;
@ -206,168 +161,25 @@ static void init_tex( void )
tex2d[1][1][3] = 255;
#endif
templat.target = PIPE_TEXTURE_2D;
templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
templat.width0 = SIZE;
templat.height0 = SIZE;
templat.depth0 = 1;
templat.array_size = 1;
templat.last_level = 0;
templat.nr_samples = 1;
templat.bind = PIPE_BIND_SAMPLER_VIEW;
texture = graw_util_create_tex2d(&info, SIZE, SIZE,
PIPE_FORMAT_B8G8R8A8_UNORM, tex2d);
sv = graw_util_create_simple_sampler_view(&info, texture);
info.ctx->set_fragment_sampler_views(info.ctx, 1, &sv);
samptex = screen->resource_create(screen,
&templat);
if (samptex == NULL)
exit(4);
u_box_2d(0,0,SIZE,SIZE, &box);
ctx->transfer_inline_write(ctx,
samptex,
0,
PIPE_TRANSFER_WRITE,
&box,
tex2d,
sizeof tex2d[0],
sizeof tex2d);
/* Possibly read back & compare against original data:
*/
if (0)
{
struct pipe_transfer *t;
uint32_t *ptr;
t = pipe_get_transfer(ctx, samptex,
0, 0, /* level, layer */
PIPE_TRANSFER_READ,
0, 0, SIZE, SIZE); /* x, y, width, height */
ptr = ctx->transfer_map(ctx, t);
if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
assert(0);
exit(9);
sampler = graw_util_create_simple_sampler(&info,
PIPE_TEX_WRAP_REPEAT,
PIPE_TEX_FILTER_NEAREST);
info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler);
}
ctx->transfer_unmap(ctx, t);
ctx->transfer_destroy(ctx, t);
}
memset(&sv_template, 0, sizeof sv_template);
sv_template.format = samptex->format;
sv_template.texture = samptex;
sv_template.swizzle_r = 0;
sv_template.swizzle_g = 1;
sv_template.swizzle_b = 2;
sv_template.swizzle_a = 3;
sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
if (sv == NULL)
exit(5);
ctx->set_fragment_sampler_views(ctx, 1, &sv);
memset(&sampler_desc, 0, sizeof sampler_desc);
sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler_desc.compare_func = 0;
sampler_desc.normalized_coords = 1;
sampler_desc.max_anisotropy = 0;
sampler = ctx->create_sampler_state(ctx, &sampler_desc);
if (sampler == NULL)
exit(6);
ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
}
static void init( void )
{
struct pipe_framebuffer_state fb;
struct pipe_resource templat;
struct pipe_surface surf_tmpl;
int i;
/* It's hard to say whether window or screen should be created
* first. Different environments would prefer one or the other.
*
* Also, no easy way of querying supported formats if the screen
* cannot be created first.
*/
for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
screen = graw_create_window_and_screen(0, 0, 300, 300,
formats[i],
&window);
if (window && screen)
break;
}
if (!screen || !window) {
fprintf(stderr, "Unable to create window\n");
if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE))
exit(1);
}
ctx = screen->context_create(screen, NULL);
if (ctx == NULL)
exit(3);
templat.target = PIPE_TEXTURE_2D;
templat.format = formats[i];
templat.width0 = WIDTH;
templat.height0 = HEIGHT;
templat.depth0 = 1;
templat.array_size = 1;
templat.last_level = 0;
templat.nr_samples = 1;
templat.bind = (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET);
rttex = screen->resource_create(screen,
&templat);
if (rttex == NULL)
exit(4);
surf_tmpl.format = templat.format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = 0;
surf_tmpl.u.tex.first_layer = 0;
surf_tmpl.u.tex.last_layer = 0;
surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
if (surf == NULL)
exit(5);
memset(&fb, 0, sizeof fb);
fb.nr_cbufs = 1;
fb.width = WIDTH;
fb.height = HEIGHT;
fb.cbufs[0] = surf;
ctx->set_framebuffer_state(ctx, &fb);
{
struct pipe_blend_state blend;
void *handle;
memset(&blend, 0, sizeof blend);
blend.rt[0].colormask = PIPE_MASK_RGBA;
handle = ctx->create_blend_state(ctx, &blend);
ctx->bind_blend_state(ctx, handle);
}
{
struct pipe_depth_stencil_alpha_state depthstencil;
void *handle;
memset(&depthstencil, 0, sizeof depthstencil);
handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
ctx->bind_depth_stencil_alpha_state(ctx, handle);
}
graw_util_default_state(&info, FALSE);
{
struct pipe_rasterizer_state rasterizer;
@ -376,11 +188,11 @@ static void init( void )
rasterizer.cull_face = PIPE_FACE_NONE;
rasterizer.gl_rasterization_rules = 1;
rasterizer.depth_clip = 1;
handle = ctx->create_rasterizer_state(ctx, &rasterizer);
ctx->bind_rasterizer_state(ctx, handle);
handle = info.ctx->create_rasterizer_state(info.ctx, &rasterizer);
info.ctx->bind_rasterizer_state(info.ctx, handle);
}
set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 1000);
init_tex();
@ -389,6 +201,7 @@ static void init( void )
set_fragment_shader();
}
static void args(int argc, char *argv[])
{
int i;

View file

@ -0,0 +1,224 @@
/* Test sRGB texturing.
*/
#include "graw_util.h"
static const int WIDTH = 600;
static const int HEIGHT = 300;
static struct graw_info info;
static struct pipe_resource *texture;
static struct pipe_sampler_view *linear_sv, *srgb_sv;
struct vertex {
float position[4];
float color[4];
};
static struct vertex vertices1[] =
{
{ { -0.1, -0.9, 0.0, 1.0 },
{ 1, 1, 0, 1 } },
{ { -0.1, 0.9, 0.0, 1.0 },
{ 1, 0, 0, 1 } },
{ {-0.9, 0.9, 0.0, 1.0 },
{ 0, 0, 0, 1 } },
{ {-0.9, -0.9, 0.0, 1.0 },
{ 0, 1, 0, 1 } },
};
static struct vertex vertices2[] =
{
{ { 0.9, -0.9, 0.0, 1.0 },
{ 1, 1, 0, 1 } },
{ { 0.9, 0.9, 0.0, 1.0 },
{ 1, 0, 0, 1 } },
{ { 0.1, 0.9, 0.0, 1.0 },
{ 0, 0, 0, 1 } },
{ { 0.1, -0.9, 0.0, 1.0 },
{ 0, 1, 0, 1 } },
};
static void
set_vertices(struct vertex *verts, unsigned num_verts)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
verts,
num_verts *sizeof(struct vertex),
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void set_vertex_shader( void )
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[1], IN[1]\n"
" 1: MOV OUT[0], IN[0]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void set_fragment_shader( void )
{
void *handle;
const char *text =
"FRAG\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR\n"
"DCL TEMP[0]\n"
"DCL SAMP[0]\n"
" 0: TXP TEMP[0], IN[0], SAMP[0], 2D\n"
" 1: MOV OUT[0], TEMP[0]\n"
" 2: END\n";
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
static void draw( void )
{
union pipe_color_union clear_color;
clear_color.f[0] = 0.5;
clear_color.f[1] = 0.5;
clear_color.f[2] = 0.5;
clear_color.f[3] = 1.0;
info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
info.ctx->set_fragment_sampler_views(info.ctx, 1, &linear_sv);
set_vertices(vertices1, 4);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
info.ctx->set_fragment_sampler_views(info.ctx, 1, &srgb_sv);
set_vertices(vertices2, 4);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
info.ctx->flush(info.ctx, NULL);
graw_util_flush_front(&info);
}
static void init_tex( void )
{
#define SIZE 64
ubyte tex2d[SIZE][SIZE][4];
int s, t;
for (s = 0; s < SIZE; s++) {
for (t = 0; t < SIZE; t++) {
tex2d[t][s][0] = 0;
tex2d[t][s][1] = s * 255 / SIZE;
tex2d[t][s][2] = t * 255 / SIZE;
tex2d[t][s][3] = 255;
}
}
texture = graw_util_create_tex2d(&info, SIZE, SIZE,
PIPE_FORMAT_B8G8R8A8_UNORM, tex2d);
{
void *sampler;
sampler = graw_util_create_simple_sampler(&info,
PIPE_TEX_WRAP_REPEAT,
PIPE_TEX_FILTER_NEAREST);
info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler);
}
/* linear sampler view */
{
struct pipe_sampler_view sv_temp;
memset(&sv_temp, 0, sizeof sv_temp);
sv_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM;
sv_temp.texture = texture;
sv_temp.swizzle_r = PIPE_SWIZZLE_RED;
sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN;
sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE;
sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA;
linear_sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_temp);
if (linear_sv == NULL)
exit(0);
}
/* srgb sampler view */
{
struct pipe_sampler_view sv_temp;
memset(&sv_temp, 0, sizeof sv_temp);
sv_temp.format = PIPE_FORMAT_B8G8R8A8_SRGB;
sv_temp.texture = texture;
sv_temp.swizzle_r = PIPE_SWIZZLE_RED;
sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN;
sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE;
sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA;
srgb_sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_temp);
if (srgb_sv == NULL)
exit(0);
}
#undef SIZE
}
static void init( void )
{
if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE))
exit(1);
graw_util_default_state(&info, FALSE);
graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 10000);
init_tex();
set_vertex_shader();
set_fragment_shader();
}
int main( int argc, char *argv[] )
{
init();
graw_set_display_func( draw );
graw_main_loop();
return 0;
}

View file

@ -0,0 +1,226 @@
/* Test texture swizzles */
#include <stdio.h>
#include "graw_util.h"
static struct graw_info info;
static struct pipe_resource *texture = NULL;
static struct pipe_sampler_view *sv = NULL;
static void *sampler = NULL;
static const int WIDTH = 300;
static const int HEIGHT = 300;
struct vertex {
float position[4];
float color[4];
};
static struct vertex vertices[] =
{
{ { 0.9, -0.9, 0.0, 1.0 },
{ 1, 0, 0, 1 } },
{ { 0.9, 0.9, 0.0, 1.0 },
{ 1, 1, 0, 1 } },
{ {-0.9, 0.9, 0.0, 1.0 },
{ 0, 1, 0, 1 } },
{ {-0.9, -0.9, 0.0, 1.0 },
{ 0, 0, 0, 1 } },
};
static void set_vertices(void)
{
struct pipe_vertex_element ve[2];
struct pipe_vertex_buffer vbuf;
void *handle;
memset(ve, 0, sizeof ve);
ve[0].src_offset = Offset(struct vertex, position);
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof(struct vertex);
vbuf.buffer_offset = 0;
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void set_vertex_shader(void)
{
void *handle;
const char *text =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC[0]\n"
" 0: MOV OUT[1], IN[1]\n"
" 1: MOV OUT[0], IN[0]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void set_fragment_shader(void)
{
void *handle;
const char *text =
"FRAG\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR\n"
"DCL SAMP[0]\n"
" 0: TXP OUT[0], IN[0], SAMP[0], 2D\n"
" 2: END\n";
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
static void draw(void)
{
union pipe_color_union clear_color;
clear_color.f[0] = 0.5;
clear_color.f[1] = 0.5;
clear_color.f[2] = 0.5;
clear_color.f[3] = 1.0;
info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
info.ctx->flush(info.ctx, NULL);
graw_util_flush_front(&info);
}
static void
init_tex(const unsigned swizzle[4])
{
#define SIZE 256
struct pipe_sampler_view sv_template;
ubyte tex2d[SIZE][SIZE][4];
int s, t;
for (s = 0; s < SIZE; s++) {
for (t = 0; t < SIZE; t++) {
tex2d[t][s][0] = 0; /*B*/
tex2d[t][s][1] = t; /*G*/
tex2d[t][s][2] = s; /*R*/
tex2d[t][s][3] = 1; /*A*/
}
}
texture = graw_util_create_tex2d(&info, SIZE, SIZE,
PIPE_FORMAT_B8G8R8A8_UNORM, tex2d);
memset(&sv_template, 0, sizeof sv_template);
sv_template.format = texture->format;
sv_template.texture = texture;
sv_template.swizzle_r = swizzle[0];
sv_template.swizzle_g = swizzle[1];
sv_template.swizzle_b = swizzle[2];
sv_template.swizzle_a = swizzle[3];
sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_template);
if (sv == NULL)
exit(5);
info.ctx->set_fragment_sampler_views(info.ctx, 1, &sv);
sampler = graw_util_create_simple_sampler(&info,
PIPE_TEX_WRAP_REPEAT,
PIPE_TEX_FILTER_NEAREST);
info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler);
#undef SIZE
}
static void
init(const unsigned swizzle[4])
{
if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE))
exit(1);
graw_util_default_state(&info, FALSE);
graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 10000);
init_tex(swizzle);
set_vertices();
set_vertex_shader();
set_fragment_shader();
}
static unsigned
char_to_swizzle(char c)
{
switch (c) {
case 'r':
return PIPE_SWIZZLE_RED;
case 'g':
return PIPE_SWIZZLE_GREEN;
case 'b':
return PIPE_SWIZZLE_BLUE;
case 'a':
return PIPE_SWIZZLE_ALPHA;
case '0':
return PIPE_SWIZZLE_ZERO;
case '1':
return PIPE_SWIZZLE_ONE;
default:
return PIPE_SWIZZLE_RED;
}
}
int main(int argc, char *argv[])
{
const char swizzle_names[] = "rgba01";
uint swizzle[4];
int i;
swizzle[0] = PIPE_SWIZZLE_RED;
swizzle[1] = PIPE_SWIZZLE_GREEN;
swizzle[2] = PIPE_SWIZZLE_BLUE;
swizzle[3] = PIPE_SWIZZLE_ALPHA;
for (i = 1; i < argc; i++) {
swizzle[i-1] = char_to_swizzle(argv[i][0]);
}
printf("Example:\n");
printf(" tex-swizzle r 0 g 1\n");
printf("Current swizzle = ");
for (i = 0; i < 4; i++) {
printf("%c", swizzle_names[swizzle[i]]);
}
printf("\n");
init(swizzle);
graw_set_display_func(draw);
graw_main_loop();
return 0;
}

View file

@ -3,36 +3,22 @@
*/
#include <stdio.h>
#include "graw_util.h"
#include "state_tracker/graw.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h" /* Offset() */
#include "util/u_draw_quad.h"
enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_NONE
};
static struct graw_info info;
static const int WIDTH = 300;
static const int HEIGHT = 300;
static struct pipe_screen *screen = NULL;
static struct pipe_context *ctx = NULL;
static struct pipe_surface *surf = NULL;
static struct pipe_resource *tex = NULL;
static void *window = NULL;
struct vertex {
float position[4];
float color[4];
};
static boolean FlatShade = FALSE;
static struct vertex vertices[3] =
{
{
@ -50,31 +36,6 @@ static struct vertex vertices[3] =
};
static void set_viewport( float x, float y,
float width, float height,
float near, float far)
{
float z = far;
float half_width = (float)width / 2.0f;
float half_height = (float)height / 2.0f;
float half_depth = ((float)far - (float)near) / 2.0f;
struct pipe_viewport_state vp;
vp.scale[0] = half_width;
vp.scale[1] = half_height;
vp.scale[2] = half_depth;
vp.scale[3] = 1.0f;
vp.translate[0] = half_width + x;
vp.translate[1] = half_height + y;
vp.translate[2] = half_depth + z;
vp.translate[3] = 0.0f;
ctx->set_viewport_state( ctx, &vp );
}
static void set_vertices( void )
{
struct pipe_vertex_element ve[2];
@ -88,20 +49,21 @@ static void set_vertices( void )
ve[1].src_offset = Offset(struct vertex, color);
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
handle = ctx->create_vertex_elements_state(ctx, 2, ve);
ctx->bind_vertex_elements_state(ctx, handle);
handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve);
info.ctx->bind_vertex_elements_state(info.ctx, handle);
vbuf.stride = sizeof( struct vertex );
vbuf.buffer_offset = 0;
vbuf.buffer = screen->user_buffer_create(screen,
vbuf.buffer = info.screen->user_buffer_create(info.screen,
vertices,
sizeof(vertices),
PIPE_BIND_VERTEX_BUFFER);
ctx->set_vertex_buffers(ctx, 1, &vbuf);
info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf);
}
static void set_vertex_shader( void )
{
void *handle;
@ -115,10 +77,11 @@ static void set_vertex_shader( void )
" 1: MOV OUT[0], IN[0]\n"
" 2: END\n";
handle = graw_parse_vertex_shader(ctx, text);
ctx->bind_vs_state(ctx, handle);
handle = graw_parse_vertex_shader(info.ctx, text);
info.ctx->bind_vs_state(info.ctx, handle);
}
static void set_fragment_shader( void )
{
void *handle;
@ -129,8 +92,8 @@ static void set_fragment_shader( void )
" 0: MOV OUT[0], IN[0]\n"
" 1: END\n";
handle = graw_parse_fragment_shader(ctx, text);
ctx->bind_fs_state(ctx, handle);
handle = graw_parse_fragment_shader(info.ctx, text);
info.ctx->bind_fs_state(info.ctx, handle);
}
@ -138,100 +101,22 @@ static void draw( void )
{
union pipe_color_union clear_color = { {1,0,1,1} };
ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, NULL);
info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
util_draw_arrays(info.ctx, PIPE_PRIM_TRIANGLES, 0, 3);
info.ctx->flush(info.ctx, NULL);
graw_save_surface_to_file(ctx, surf, NULL);
graw_save_surface_to_file(info.ctx, info.color_surf[0], NULL);
screen->flush_frontbuffer(screen, tex, 0, 0, window);
graw_util_flush_front(&info);
}
static void init( void )
{
struct pipe_framebuffer_state fb;
struct pipe_resource templat;
struct pipe_surface surf_tmpl;
int i;
/* It's hard to say whether window or screen should be created
* first. Different environments would prefer one or the other.
*
* Also, no easy way of querying supported formats if the screen
* cannot be created first.
*/
for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
screen = graw_create_window_and_screen(0, 0, 300, 300,
formats[i],
&window);
if (window && screen)
break;
}
if (!screen || !window) {
fprintf(stderr, "Unable to create window\n");
if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE))
exit(1);
}
ctx = screen->context_create(screen, NULL);
if (ctx == NULL) {
fprintf(stderr, "Unable to create context!\n");
exit(3);
}
templat.target = PIPE_TEXTURE_2D;
templat.format = formats[i];
templat.width0 = WIDTH;
templat.height0 = HEIGHT;
templat.depth0 = 1;
templat.array_size = 1;
templat.last_level = 0;
templat.nr_samples = 1;
templat.bind = (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET);
tex = screen->resource_create(screen,
&templat);
if (tex == NULL) {
fprintf(stderr, "Unable to create screen texture!\n");
exit(4);
}
surf_tmpl.format = templat.format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = 0;
surf_tmpl.u.tex.first_layer = 0;
surf_tmpl.u.tex.last_layer = 0;
surf = ctx->create_surface(ctx, tex, &surf_tmpl);
if (surf == NULL) {
fprintf(stderr, "Unable to create tex surface!\n");
exit(5);
}
memset(&fb, 0, sizeof fb);
fb.nr_cbufs = 1;
fb.width = WIDTH;
fb.height = HEIGHT;
fb.cbufs[0] = surf;
ctx->set_framebuffer_state(ctx, &fb);
{
struct pipe_blend_state blend;
void *handle;
memset(&blend, 0, sizeof blend);
blend.rt[0].colormask = PIPE_MASK_RGBA;
handle = ctx->create_blend_state(ctx, &blend);
ctx->bind_blend_state(ctx, handle);
}
{
struct pipe_depth_stencil_alpha_state depthstencil;
void *handle;
memset(&depthstencil, 0, sizeof depthstencil);
handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
ctx->bind_depth_stencil_alpha_state(ctx, handle);
}
graw_util_default_state(&info, FALSE);
{
struct pipe_rasterizer_state rasterizer;
@ -239,12 +124,15 @@ static void init( void )
memset(&rasterizer, 0, sizeof rasterizer);
rasterizer.cull_face = PIPE_FACE_NONE;
rasterizer.gl_rasterization_rules = 1;
rasterizer.flatshade = FlatShade;
rasterizer.depth_clip = 1;
handle = ctx->create_rasterizer_state(ctx, &rasterizer);
ctx->bind_rasterizer_state(ctx, handle);
handle = info.ctx->create_rasterizer_state(info.ctx, &rasterizer);
info.ctx->bind_rasterizer_state(info.ctx, handle);
}
set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 1000);
set_vertices();
set_vertex_shader();
set_fragment_shader();
@ -256,11 +144,18 @@ static void args(int argc, char *argv[])
for (i = 1; i < argc; ) {
if (graw_parse_args(&i, argc, argv)) {
continue;
/* ok */
}
else if (strcmp(argv[i], "-f") == 0) {
FlatShade = TRUE;
i++;
}
else {
printf("Invalid arg %s\n", argv[i]);
exit(1);
}
}
}
int main( int argc, char *argv[] )
{