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_debug_image.h"
13#include "util/u_draw_quad.h"
14#include "util/u_format.h"
15#include "util/u_inlines.h"
16#include "util/u_memory.h"
17
18
19struct 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
30static inline boolean
31graw_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
147static inline void
148graw_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
184static inline void
185graw_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
208static inline void
209graw_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
216static inline struct pipe_resource *
217graw_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
281static inline void *
282graw_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
307static inline struct pipe_sampler_view *
308graw_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