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
18struct 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
29static INLINE boolean
30graw_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
149static INLINE void
150graw_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
185static INLINE void
186graw_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
211static INLINE void
212graw_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
219static INLINE struct pipe_resource *
220graw_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
284static INLINE void *
285graw_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
310static INLINE struct pipe_sampler_view *
311graw_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