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