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