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_TRANSFER_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_TRANSFER_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