Path: blob/21.2-virgl/src/gallium/tests/graw/gs-test.c
4565 views
/* Display a cleared blue window. This demo has no dependencies on1* any utility code, just the graw interface and gallium.2*/34#include "frontend/graw.h"5#include "pipe/p_screen.h"6#include "pipe/p_context.h"7#include "pipe/p_shader_tokens.h"8#include "pipe/p_state.h"9#include "pipe/p_defines.h"10#include <stdio.h> /* for fread(), etc */1112#include "util/u_inlines.h"13#include "util/u_memory.h" /* Offset() */14#include "util/u_draw_quad.h"15#include "util/u_box.h"1617static const char *filename = NULL;18unsigned show_fps = 0;19unsigned draw_strip = 0;202122static void usage(char *name)23{24fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);25#ifndef _WIN3226fprintf(stderr, "\n" );27fprintf(stderr, "options:\n");28fprintf(stderr, " -fps show frames per second\n");29fprintf(stderr, " -strip renders a triangle strip\n");30#endif31}323334enum pipe_format formats[] = {35PIPE_FORMAT_R8G8B8A8_UNORM,36PIPE_FORMAT_B8G8R8A8_UNORM,37PIPE_FORMAT_NONE38};3940static const int WIDTH = 250;41static const int HEIGHT = 250;4243static struct pipe_screen *screen = NULL;44static struct pipe_context *ctx = NULL;45static struct pipe_resource *rttex = NULL;46static struct pipe_resource *constbuf1 = NULL;47static struct pipe_resource *constbuf2 = NULL;48static struct pipe_surface *surf = NULL;49static struct pipe_sampler_view *sv = NULL;50static void *sampler = NULL;51static void *window = NULL;52static struct pipe_resource *samptex = NULL;5354struct vertex {55float position[4];56float color[4];57float texcoord[4];58float generic[4];59};6061/* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension62* so that the final images are the same.63*/64static struct vertex vertices[] =65{66{ { 0.9, 0.9, 0.0, 1.0 },67{ 0, 0, 1, 1 },68{ 1, 1, 0, 1 },69{ 1, 0, 1, 0 }70},7172{ { 0.9, -0.9, 0.0, 1.0 },73{ 1, 0, 0, 1 },74{ 1, -1, 0, 1 },75{ 0, 1, 0, 1 }76},7778{ {-0.9, 0.0, 0.0, 1.0 },79{ 0, 1, 0, 1 },80{ -1, 0, 0, 1 },81{ 0, 0, 1, 1 }82},83};8485static struct vertex vertices_strip[] =86{87{ { 0.9, 0.9, 0.0, 1.0 },88{ 0, 0, 1, 1 },89{ 1, 1, 0, 1 },90{ 1, 0, 0, 1 }91},9293{ { 0.9, -0.9, 0.0, 1.0 },94{ 1, 0, 0, 1 },95{ 1, -1, 0, 1 },96{ 0, 1, 0, 1 }97},9899{ {-0.9, 0.9, 0.0, 1.0 },100{ 0, 1, 0, 1 },101{ -1, 1, 0, 1 },102{ 0, 0, 1, 1 }103},104105{ {-0.9, -0.9, 0.0, 1.0 },106{ 1, 1, 0, 1 },107{ -1, -1, 0, 1 },108{ 1, 1, 0, 1 }109},110};111112static float constants1[] =113{ 0.4, 0, 0, 1,1141, 1, 1, 1,1152, 2, 2, 2,1164, 8, 16, 32,1171183, 0, 0, 0,1190, .5, 0, 0,1200, 0, 1, 0,1210, 0, 0, 1,1221231, 0, 0, 0.5,1240, 1, 0, 0.5,1250, 0, 1, 0,1260, 0, 0, 1,127};128129130static float constants2[] =131{ 1, 0, 0, 1,1320, 1, 0, 1,1330, 0, 1, 1,1340, 0, 0, 1,1351361, 1, 0, 1,1371, .5, 0, 1,1380, 1, 1, 1,1391, 0, 1, 1,1401411, 0, 0, 0.5,1420, 1, 0, 0.5,1430, 0, 1, 0,1440, 0, 0, 1,145};146147148static void init_fs_constbuf( void )149{150struct pipe_resource templat;151152memset(&templat, 0, sizeof(templat));153templat.target = PIPE_BUFFER;154templat.format = PIPE_FORMAT_R8_UNORM;155templat.width0 = sizeof(constants1);156templat.height0 = 1;157templat.depth0 = 1;158templat.array_size = 1;159templat.last_level = 0;160templat.bind = PIPE_BIND_CONSTANT_BUFFER;161162constbuf1 = screen->resource_create(screen, &templat);163if (constbuf1 == NULL)164exit(4);165constbuf2 = screen->resource_create(screen, &templat);166if (constbuf2 == NULL)167exit(4);168169{170ctx->buffer_subdata(ctx, constbuf1,171PIPE_MAP_WRITE,1720, sizeof(constants1), constants1);173174pipe_set_constant_buffer(ctx,175PIPE_SHADER_GEOMETRY, 0,176constbuf1);177}178{179ctx->buffer_subdata(ctx, constbuf2,180PIPE_MAP_WRITE,1810, sizeof(constants2), constants2);182183pipe_set_constant_buffer(ctx,184PIPE_SHADER_GEOMETRY, 1,185constbuf2);186}187}188189190static void set_viewport( float x, float y,191float width, float height,192float zNear, float zFar)193{194float z = zFar;195float half_width = (float)width / 2.0f;196float half_height = (float)height / 2.0f;197float half_depth = ((float)zFar - (float)zNear) / 2.0f;198struct pipe_viewport_state vp;199200vp.scale[0] = half_width;201vp.scale[1] = half_height;202vp.scale[2] = half_depth;203204vp.translate[0] = half_width + x;205vp.translate[1] = half_height + y;206vp.translate[2] = half_depth + z;207208vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;209vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;210vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;211vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;212213ctx->set_viewport_states( ctx, 0, 1, &vp );214}215216static void set_vertices( void )217{218struct pipe_vertex_element ve[4];219struct pipe_vertex_buffer vbuf;220void *handle;221222memset(ve, 0, sizeof ve);223224ve[0].src_offset = Offset(struct vertex, position);225ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;226ve[1].src_offset = Offset(struct vertex, color);227ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;228ve[2].src_offset = Offset(struct vertex, texcoord);229ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;230ve[3].src_offset = Offset(struct vertex, generic);231ve[3].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;232233handle = ctx->create_vertex_elements_state(ctx, 4, ve);234ctx->bind_vertex_elements_state(ctx, handle);235236memset(&vbuf, 0, sizeof vbuf);237238vbuf.stride = sizeof( struct vertex );239vbuf.buffer_offset = 0;240if (draw_strip) {241vbuf.buffer.resource = pipe_buffer_create_with_data(ctx,242PIPE_BIND_VERTEX_BUFFER,243PIPE_USAGE_DEFAULT,244sizeof(vertices_strip),245vertices_strip);246} else {247vbuf.buffer.resource = pipe_buffer_create_with_data(ctx,248PIPE_BIND_VERTEX_BUFFER,249PIPE_USAGE_DEFAULT,250sizeof(vertices),251vertices);252}253254ctx->set_vertex_buffers(ctx, 0, 1, 0, false, &vbuf);255}256257static void set_vertex_shader( void )258{259void *handle;260const char *text =261"VERT\n"262"DCL IN[0]\n"263"DCL IN[1]\n"264"DCL IN[2]\n"265"DCL IN[3]\n"266"DCL OUT[0], POSITION\n"267"DCL OUT[1], COLOR[0]\n"268"DCL OUT[2], GENERIC[0]\n"269"DCL OUT[3], GENERIC[1]\n"270" MOV OUT[0], IN[0]\n"271" MOV OUT[1], IN[1]\n"272" MOV OUT[2], IN[2]\n"273" MOV OUT[3], IN[3]\n"274" END\n";275276handle = graw_parse_vertex_shader(ctx, text);277ctx->bind_vs_state(ctx, handle);278}279280static void set_fragment_shader( void )281{282void *handle;283const char *text =284"FRAG\n"285"DCL IN[0], COLOR, LINEAR\n"286"DCL OUT[0], COLOR\n"287" 0: MOV OUT[0], IN[0]\n"288" 1: END\n";289290handle = graw_parse_fragment_shader(ctx, text);291ctx->bind_fs_state(ctx, handle);292}293294295static void set_geometry_shader( void )296{297FILE *f;298char buf[50000];299void *handle;300int sz;301302if ((f = fopen(filename, "r")) == NULL) {303fprintf(stderr, "Couldn't open %s\n", filename);304exit(1);305}306307sz = fread(buf, 1, sizeof(buf), f);308if (!feof(f)) {309printf("file too long\n");310exit(1);311}312printf("%.*s\n", sz, buf);313buf[sz] = 0;314315handle = graw_parse_geometry_shader(ctx, buf);316ctx->bind_gs_state(ctx, handle);317fclose(f);318}319320321static void draw( void )322{323union pipe_color_union clear_color = { {.1,.3,.5,0} };324325ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);326if (draw_strip)327util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);328else329util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);330331ctx->flush(ctx, NULL, 0);332333graw_save_surface_to_file(ctx, surf, NULL);334335screen->flush_frontbuffer(screen, ctx, rttex, 0, 0, window, NULL);336}337338#define SIZE 16339340static void init_tex( void )341{342struct pipe_sampler_view sv_template;343struct pipe_sampler_state sampler_desc;344struct pipe_resource templat;345struct pipe_box box;346ubyte tex2d[SIZE][SIZE][4];347int s, t;348349#if (SIZE != 2)350for (s = 0; s < SIZE; s++) {351for (t = 0; t < SIZE; t++) {352if (0) {353int x = (s ^ t) & 1;354tex2d[t][s][0] = (x) ? 0 : 63;355tex2d[t][s][1] = (x) ? 0 : 128;356tex2d[t][s][2] = 0;357tex2d[t][s][3] = 0xff;358}359else {360int x = ((s ^ t) >> 2) & 1;361tex2d[t][s][0] = s*255/(SIZE-1);362tex2d[t][s][1] = t*255/(SIZE-1);363tex2d[t][s][2] = (x) ? 0 : 128;364tex2d[t][s][3] = 0xff;365}366}367}368#else369tex2d[0][0][0] = 0;370tex2d[0][0][1] = 255;371tex2d[0][0][2] = 255;372tex2d[0][0][3] = 0;373374tex2d[0][1][0] = 0;375tex2d[0][1][1] = 0;376tex2d[0][1][2] = 255;377tex2d[0][1][3] = 255;378379tex2d[1][0][0] = 255;380tex2d[1][0][1] = 255;381tex2d[1][0][2] = 0;382tex2d[1][0][3] = 255;383384tex2d[1][1][0] = 255;385tex2d[1][1][1] = 0;386tex2d[1][1][2] = 0;387tex2d[1][1][3] = 255;388#endif389390memset(&templat, 0, sizeof(templat));391templat.target = PIPE_TEXTURE_2D;392templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;393templat.width0 = SIZE;394templat.height0 = SIZE;395templat.depth0 = 1;396templat.array_size = 1;397templat.last_level = 0;398templat.bind = PIPE_BIND_SAMPLER_VIEW;399400401samptex = screen->resource_create(screen,402&templat);403if (samptex == NULL)404exit(4);405406u_box_2d(0,0,SIZE,SIZE, &box);407408ctx->texture_subdata(ctx,409samptex,4100,411PIPE_MAP_WRITE,412&box,413tex2d,414sizeof tex2d[0],415sizeof tex2d);416417/* Possibly read back & compare against original data:418*/419if (0)420{421struct pipe_transfer *t;422uint32_t *ptr;423ptr = pipe_texture_map(ctx, samptex,4240, 0, /* level, layer */425PIPE_MAP_READ,4260, 0, SIZE, SIZE, &t); /* x, y, width, height */427428if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {429assert(0);430exit(9);431}432433ctx->texture_unmap(ctx, t);434}435436memset(&sv_template, 0, sizeof sv_template);437sv_template.format = samptex->format;438sv_template.texture = samptex;439sv_template.swizzle_r = 0;440sv_template.swizzle_g = 1;441sv_template.swizzle_b = 2;442sv_template.swizzle_a = 3;443sv = ctx->create_sampler_view(ctx, samptex, &sv_template);444if (sv == NULL)445exit(5);446447ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, &sv);448449450memset(&sampler_desc, 0, sizeof sampler_desc);451sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;452sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;453sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;454sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;455sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;456sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;457sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;458sampler_desc.compare_func = 0;459sampler_desc.normalized_coords = 1;460sampler_desc.max_anisotropy = 0;461462sampler = ctx->create_sampler_state(ctx, &sampler_desc);463if (sampler == NULL)464exit(6);465466ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler);467468}469470static void init( void )471{472struct pipe_framebuffer_state fb;473struct pipe_resource templat;474struct pipe_surface surf_tmpl;475int i;476477/* It's hard to say whether window or screen should be created478* first. Different environments would prefer one or the other.479*480* Also, no easy way of querying supported formats if the screen481* cannot be created first.482*/483for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {484screen = graw_create_window_and_screen(0, 0, 300, 300,485formats[i],486&window);487if (window && screen)488break;489}490if (!screen || !window) {491fprintf(stderr, "Unable to create window\n");492exit(1);493}494495ctx = screen->context_create(screen, NULL, 0);496if (ctx == NULL)497exit(3);498499memset(&templat, 0, sizeof(templat));500templat.target = PIPE_TEXTURE_2D;501templat.format = formats[i];502templat.width0 = WIDTH;503templat.height0 = HEIGHT;504templat.depth0 = 1;505templat.array_size = 1;506templat.last_level = 0;507templat.bind = (PIPE_BIND_RENDER_TARGET |508PIPE_BIND_DISPLAY_TARGET);509510rttex = screen->resource_create(screen,511&templat);512if (rttex == NULL)513exit(4);514515surf_tmpl.format = templat.format;516surf_tmpl.u.tex.level = 0;517surf_tmpl.u.tex.first_layer = 0;518surf_tmpl.u.tex.last_layer = 0;519surf = ctx->create_surface(ctx, rttex, &surf_tmpl);520if (surf == NULL)521exit(5);522523memset(&fb, 0, sizeof fb);524fb.nr_cbufs = 1;525fb.width = WIDTH;526fb.height = HEIGHT;527fb.cbufs[0] = surf;528529ctx->set_framebuffer_state(ctx, &fb);530531{532struct pipe_blend_state blend;533void *handle;534memset(&blend, 0, sizeof blend);535blend.rt[0].colormask = PIPE_MASK_RGBA;536handle = ctx->create_blend_state(ctx, &blend);537ctx->bind_blend_state(ctx, handle);538}539540{541struct pipe_depth_stencil_alpha_state depthstencil;542void *handle;543memset(&depthstencil, 0, sizeof depthstencil);544handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);545ctx->bind_depth_stencil_alpha_state(ctx, handle);546}547548{549struct pipe_rasterizer_state rasterizer;550void *handle;551memset(&rasterizer, 0, sizeof rasterizer);552rasterizer.cull_face = PIPE_FACE_NONE;553rasterizer.half_pixel_center = 1;554rasterizer.bottom_edge_rule = 1;555rasterizer.depth_clip_near = 1;556rasterizer.depth_clip_far = 1;557handle = ctx->create_rasterizer_state(ctx, &rasterizer);558ctx->bind_rasterizer_state(ctx, handle);559}560561set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);562563init_tex();564init_fs_constbuf();565566set_vertices();567set_vertex_shader();568set_fragment_shader();569set_geometry_shader();570}571572static void args(int argc, char *argv[])573{574int i;575576for (i = 1; i < argc;) {577if (graw_parse_args(&i, argc, argv)) {578continue;579}580if (strcmp(argv[i], "-fps") == 0) {581show_fps = 1;582i++;583}584else if (strcmp(argv[i], "-strip") == 0) {585draw_strip = 1;586i++;587}588else if (i == argc - 1) {589filename = argv[i];590i++;591}592else {593usage(argv[0]);594exit(1);595}596}597598if (!filename) {599usage(argv[0]);600exit(1);601}602}603604int main( int argc, char *argv[] )605{606args(argc,argv);607init();608609graw_set_display_func( draw );610graw_main_loop();611return 0;612}613614615