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