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    vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
205    vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
206    vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
207    vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
208 
209    info->ctx->set_viewport_states(info->ctx, 0, 1, &vp);
210 }
211 
212 
213 static inline void
graw_util_flush_front(const struct graw_info * info)214 graw_util_flush_front(const struct graw_info *info)
215 {
216    info->screen->flush_frontbuffer(info->screen, info->ctx, info->color_buf[0],
217                                    0, 0, info->window, NULL);
218 }
219 
220 
221 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)222 graw_util_create_tex2d(const struct graw_info *info,
223                        int width, int height, enum pipe_format format,
224                        const void *data)
225 {
226    const int row_stride = width * util_format_get_blocksize(format);
227    const int image_bytes = row_stride * height;
228    struct pipe_resource temp, *tex;
229    struct pipe_box box;
230 
231    memset(&temp, 0, sizeof(temp));
232    temp.target = PIPE_TEXTURE_2D;
233    temp.format = format;
234    temp.width0 = width;
235    temp.height0 = height;
236    temp.depth0 = 1;
237    temp.last_level = 0;
238    temp.array_size = 1;
239    temp.bind = PIPE_BIND_SAMPLER_VIEW;
240 
241    tex = info->screen->resource_create(info->screen, &temp);
242    if (!tex) {
243       debug_printf("graw: failed to create texture\n");
244       return NULL;
245    }
246 
247    u_box_2d(0, 0, width, height, &box);
248 
249    info->ctx->texture_subdata(info->ctx,
250                               tex,
251                               0,
252                               PIPE_MAP_WRITE,
253                               &box,
254                               data,
255                               row_stride,
256                               image_bytes);
257 
258    /* Possibly read back & compare against original data:
259     */
260 #if 0
261    {
262       struct pipe_transfer *t;
263       uint32_t *ptr;
264       t = pipe_texture_map(info->ctx, samptex,
265                             0, 0, /* level, layer */
266                             PIPE_MAP_READ,
267                             0, 0, SIZE, SIZE); /* x, y, width, height */
268 
269       ptr = info->ctx->texture_map(info->ctx, t);
270 
271       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
272          assert(0);
273          exit(9);
274       }
275 
276       info->ctx->texture_unmap(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_X;
321    sv_temp.swizzle_g = PIPE_SWIZZLE_Y;
322    sv_temp.swizzle_b = PIPE_SWIZZLE_Z;
323    sv_temp.swizzle_a = PIPE_SWIZZLE_W;
324 
325    sv = info->ctx->create_sampler_view(info->ctx, texture, &sv_temp);
326 
327    return sv;
328 }
329 
330