1
2 #include "state_tracker/graw.h"
3
4 #include "pipe/p_context.h"
5 #include "pipe/p_defines.h"
6 #include "pipe/p_screen.h"
7 #include "pipe/p_shader_tokens.h"
8 #include "pipe/p_state.h"
9
10 #include "util/u_box.h"
11 #include "util/u_debug.h"
12 #include "util/u_draw_quad.h"
13 #include "util/u_format.h"
14 #include "util/u_inlines.h"
15 #include "util/u_memory.h"
16
17
18 struct graw_info
19 {
20 struct pipe_screen *screen;
21 struct pipe_context *ctx;
22 struct pipe_resource *color_buf[PIPE_MAX_COLOR_BUFS], *zs_buf;
23 struct pipe_surface *color_surf[PIPE_MAX_COLOR_BUFS], *zs_surf;
24 void *window;
25 };
26
27
28
29 static INLINE boolean
graw_util_create_window(struct graw_info * info,int width,int height,int num_cbufs,bool zstencil_buf)30 graw_util_create_window(struct graw_info *info,
31 int width, int height,
32 int num_cbufs, bool zstencil_buf)
33 {
34 static const enum pipe_format formats[] = {
35 PIPE_FORMAT_R8G8B8A8_UNORM,
36 PIPE_FORMAT_B8G8R8A8_UNORM,
37 PIPE_FORMAT_NONE
38 };
39 enum pipe_format format;
40 struct pipe_resource resource_temp;
41 struct pipe_surface surface_temp;
42 int i;
43
44 memset(info, 0, sizeof(*info));
45
46 /* It's hard to say whether window or screen should be created
47 * first. Different environments would prefer one or the other.
48 *
49 * Also, no easy way of querying supported formats if the screen
50 * cannot be created first.
51 */
52 for (i = 0; info->window == NULL && formats[i] != PIPE_FORMAT_NONE; i++) {
53 info->screen = graw_create_window_and_screen(0, 0, width, height,
54 formats[i],
55 &info->window);
56 format = formats[i];
57 }
58 if (!info->screen || !info->window) {
59 debug_printf("graw: Failed to create screen/window\n");
60 return FALSE;
61 }
62
63 info->ctx = info->screen->context_create(info->screen, NULL);
64 if (info->ctx == NULL) {
65 debug_printf("graw: Failed to create context\n");
66 return FALSE;
67 }
68
69 for (i = 0; i < num_cbufs; i++) {
70 /* create color texture */
71 resource_temp.target = PIPE_TEXTURE_2D;
72 resource_temp.format = format;
73 resource_temp.width0 = width;
74 resource_temp.height0 = height;
75 resource_temp.depth0 = 1;
76 resource_temp.array_size = 1;
77 resource_temp.last_level = 0;
78 resource_temp.nr_samples = 1;
79 resource_temp.bind = (PIPE_BIND_RENDER_TARGET |
80 PIPE_BIND_DISPLAY_TARGET);
81 info->color_buf[i] = info->screen->resource_create(info->screen,
82 &resource_temp);
83 if (info->color_buf[i] == NULL) {
84 debug_printf("graw: Failed to create color texture\n");
85 return FALSE;
86 }
87
88 /* create color surface */
89 surface_temp.format = resource_temp.format;
90 surface_temp.usage = PIPE_BIND_RENDER_TARGET;
91 surface_temp.u.tex.level = 0;
92 surface_temp.u.tex.first_layer = 0;
93 surface_temp.u.tex.last_layer = 0;
94 info->color_surf[i] = info->ctx->create_surface(info->ctx,
95 info->color_buf[i],
96 &surface_temp);
97 if (info->color_surf[i] == NULL) {
98 debug_printf("graw: Failed to get color surface\n");
99 return FALSE;
100 }
101 }
102
103 /* create Z texture (XXX try other Z/S formats if needed) */
104 resource_temp.target = PIPE_TEXTURE_2D;
105 resource_temp.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
106 resource_temp.width0 = width;
107 resource_temp.height0 = height;
108 resource_temp.depth0 = 1;
109 resource_temp.array_size = 1;
110 resource_temp.last_level = 0;
111 resource_temp.nr_samples = 1;
112 resource_temp.bind = PIPE_BIND_DEPTH_STENCIL;
113 info->zs_buf = info->screen->resource_create(info->screen, &resource_temp);
114 if (!info->zs_buf) {
115 debug_printf("graw: Failed to create Z texture\n");
116 return FALSE;
117 }
118
119 /* create z surface */
120 surface_temp.format = resource_temp.format;
121 surface_temp.usage = PIPE_BIND_DEPTH_STENCIL;
122 surface_temp.u.tex.level = 0;
123 surface_temp.u.tex.first_layer = 0;
124 surface_temp.u.tex.last_layer = 0;
125 info->zs_surf = info->ctx->create_surface(info->ctx,
126 info->zs_buf,
127 &surface_temp);
128 if (info->zs_surf == NULL) {
129 debug_printf("graw: Failed to get Z surface\n");
130 return FALSE;
131 }
132
133 {
134 struct pipe_framebuffer_state fb;
135 memset(&fb, 0, sizeof fb);
136 fb.nr_cbufs = num_cbufs;
137 fb.width = width;
138 fb.height = height;
139 for (i = 0; i < num_cbufs; i++)
140 fb.cbufs[i] = info->color_surf[i];
141 fb.zsbuf = info->zs_surf;
142 info->ctx->set_framebuffer_state(info->ctx, &fb);
143 }
144
145 return TRUE;
146 }
147
148
149 static INLINE void
graw_util_default_state(struct graw_info * info,boolean depth_test)150 graw_util_default_state(struct graw_info *info, boolean depth_test)
151 {
152 {
153 struct pipe_blend_state blend;
154 void *handle;
155 memset(&blend, 0, sizeof blend);
156 blend.rt[0].colormask = PIPE_MASK_RGBA;
157 handle = info->ctx->create_blend_state(info->ctx, &blend);
158 info->ctx->bind_blend_state(info->ctx, handle);
159 }
160
161 {
162 struct pipe_depth_stencil_alpha_state depthStencilAlpha;
163 void *handle;
164 memset(&depthStencilAlpha, 0, sizeof depthStencilAlpha);
165 depthStencilAlpha.depth.enabled = depth_test;
166 depthStencilAlpha.depth.writemask = 1;
167 depthStencilAlpha.depth.func = PIPE_FUNC_LESS;
168 handle = info->ctx->create_depth_stencil_alpha_state(info->ctx,
169 &depthStencilAlpha);
170 info->ctx->bind_depth_stencil_alpha_state(info->ctx, handle);
171 }
172
173 {
174 struct pipe_rasterizer_state rasterizer;
175 void *handle;
176 memset(&rasterizer, 0, sizeof rasterizer);
177 rasterizer.cull_face = PIPE_FACE_NONE;
178 rasterizer.gl_rasterization_rules = 1;
179 handle = info->ctx->create_rasterizer_state(info->ctx, &rasterizer);
180 info->ctx->bind_rasterizer_state(info->ctx, handle);
181 }
182 }
183
184
185 static INLINE void
graw_util_viewport(struct graw_info * info,float x,float y,float width,float height,float near,float far)186 graw_util_viewport(struct graw_info *info,
187 float x, float y,
188 float width, float height,
189 float near, float far)
190 {
191 float z = near;
192 float half_width = width / 2.0f;
193 float half_height = height / 2.0f;
194 float half_depth = (far - near) / 2.0f;
195 struct pipe_viewport_state vp;
196
197 vp.scale[0] = half_width;
198 vp.scale[1] = half_height;
199 vp.scale[2] = half_depth;
200 vp.scale[3] = 1.0f;
201
202 vp.translate[0] = half_width + x;
203 vp.translate[1] = half_height + y;
204 vp.translate[2] = half_depth + z;
205 vp.translate[3] = 0.0f;
206
207 info->ctx->set_viewport_state(info->ctx, &vp);
208 }
209
210
211 static INLINE void
graw_util_flush_front(const struct graw_info * info)212 graw_util_flush_front(const struct graw_info *info)
213 {
214 info->screen->flush_frontbuffer(info->screen, info->color_buf[0],
215 0, 0, info->window);
216 }
217
218
219 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)220 graw_util_create_tex2d(const struct graw_info *info,
221 int width, int height, enum pipe_format format,
222 const void *data)
223 {
224 const int row_stride = width * util_format_get_blocksize(format);
225 const int image_bytes = row_stride * height;
226 struct pipe_resource temp, *tex;
227 struct pipe_box box;
228
229 temp.target = PIPE_TEXTURE_2D;
230 temp.format = PIPE_FORMAT_B8G8R8A8_UNORM;
231 temp.width0 = width;
232 temp.height0 = height;
233 temp.depth0 = 1;
234 temp.last_level = 0;
235 temp.array_size = 1;
236 temp.nr_samples = 1;
237 temp.bind = PIPE_BIND_SAMPLER_VIEW;
238
239 tex = info->screen->resource_create(info->screen, &temp);
240 if (!tex) {
241 debug_printf("graw: failed to create texture\n");
242 return NULL;
243 }
244
245 u_box_2d(0, 0, width, height, &box);
246
247 info->ctx->transfer_inline_write(info->ctx,
248 tex,
249 0,
250 PIPE_TRANSFER_WRITE,
251 &box,
252 data,
253 row_stride,
254 image_bytes);
255
256 /* Possibly read back & compare against original data:
257 */
258 #if 0
259 {
260 struct pipe_transfer *t;
261 uint32_t *ptr;
262 t = pipe_get_transfer(info->ctx, samptex,
263 0, 0, /* level, layer */
264 PIPE_TRANSFER_READ,
265 0, 0, SIZE, SIZE); /* x, y, width, height */
266
267 ptr = info->ctx->transfer_map(info->ctx, t);
268
269 if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
270 assert(0);
271 exit(9);
272 }
273
274 info->ctx->transfer_unmap(info->ctx, t);
275
276 info->ctx->transfer_destroy(info->ctx, t);
277 }
278 #endif
279
280 return tex;
281 }
282
283
284 static INLINE void *
graw_util_create_simple_sampler(const struct graw_info * info,unsigned wrap_mode,unsigned img_filter)285 graw_util_create_simple_sampler(const struct graw_info *info,
286 unsigned wrap_mode,
287 unsigned img_filter)
288 {
289 struct pipe_sampler_state sampler_desc;
290 void *sampler;
291
292 memset(&sampler_desc, 0, sizeof sampler_desc);
293 sampler_desc.wrap_s =
294 sampler_desc.wrap_t =
295 sampler_desc.wrap_r = wrap_mode;
296 sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
297 sampler_desc.min_img_filter =
298 sampler_desc.mag_img_filter = img_filter;
299 sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
300 sampler_desc.compare_func = 0;
301 sampler_desc.normalized_coords = 1;
302 sampler_desc.max_anisotropy = 0;
303
304 sampler = info->ctx->create_sampler_state(info->ctx, &sampler_desc);
305
306 return sampler;
307 }
308
309
310 static INLINE struct pipe_sampler_view *
graw_util_create_simple_sampler_view(const struct graw_info * info,struct pipe_resource * texture)311 graw_util_create_simple_sampler_view(const struct graw_info *info,
312 struct pipe_resource *texture)
313 {
314 struct pipe_sampler_view sv_temp;
315 struct pipe_sampler_view *sv;
316
317 memset(&sv_temp, 0, sizeof(sv_temp));
318 sv_temp.format = texture->format;
319 sv_temp.texture = texture;
320 sv_temp.swizzle_r = PIPE_SWIZZLE_RED;
321 sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN;
322 sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE;
323 sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA;
324
325 sv = info->ctx->create_sampler_view(info->ctx, texture, &sv_temp);
326
327 return sv;
328 }
329
330