1 /* 2 * Copyright 2012-2014, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Artur Wyszynski, harakash (at) gmail.com 7 * Alexander von Gluck IV, kallisti5 (at) unixzen.com 8 */ 9 10 #include "hgl_context.h" 11 12 #include <stdio.h> 13 14 #include "pipe/p_format.h" 15 #include "util/u_atomic.h" 16 #include "util/u_format.h" 17 #include "util/u_memory.h" 18 #include "util/u_inlines.h" 19 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ 20 21 #include "GLView.h" 22 23 24 #ifdef DEBUG 25 # define TRACE(x...) printf("hgl:state_tracker: " x) 26 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) 27 #else 28 # define TRACE(x...) 29 # define CALLED() 30 #endif 31 #define ERROR(x...) printf("hgl:state_tracker: " x) 32 33 34 // Perform a safe void to hgl_context cast 35 static inline struct hgl_context* 36 hgl_st_context(struct st_context_iface *stctxi) 37 { 38 struct hgl_context* context; 39 assert(stctxi); 40 context = (struct hgl_context*)stctxi->st_manager_private; 41 assert(context); 42 return context; 43 } 44 45 46 // Perform a safe void to hgl_buffer cast 47 static inline struct hgl_buffer* 48 hgl_st_framebuffer(struct st_framebuffer_iface *stfbi) 49 { 50 struct hgl_buffer* buffer; 51 assert(stfbi); 52 buffer = (struct hgl_buffer*)stfbi->st_manager_private; 53 assert(buffer); 54 return buffer; 55 } 56 57 58 static boolean 59 hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi, 60 struct st_framebuffer_iface* stfbi, enum st_attachment_type statt) 61 { 62 CALLED(); 63 64 //struct hgl_context* context = hgl_st_context(stctxi); 65 //struct hgl_buffer* buffer = hgl_st_context(stfbi); 66 67 #if 0 68 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 69 pipe_mutex_lock(stwfb->fb->mutex); 70 71 struct pipe_resource* resource = textures[statt]; 72 if (resource) 73 stw_framebuffer_present_locked(...); 74 #endif 75 76 return TRUE; 77 } 78 79 80 static boolean 81 hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, 82 unsigned width, unsigned height, unsigned mask) 83 { 84 struct hgl_buffer* buffer; 85 enum st_attachment_type i; 86 struct pipe_resource templat; 87 88 CALLED(); 89 90 buffer = hgl_st_framebuffer(stfbi); 91 92 if (buffer->width != width || buffer->height != height) { 93 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 94 pipe_resource_reference(&buffer->textures[i], NULL); 95 } 96 97 memset(&templat, 0, sizeof(templat)); 98 templat.target = buffer->target; 99 templat.width0 = width; 100 templat.height0 = height; 101 templat.depth0 = 1; 102 templat.array_size = 1; 103 templat.last_level = 0; 104 105 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 106 enum pipe_format format; 107 unsigned bind; 108 109 switch (i) { 110 case ST_ATTACHMENT_FRONT_LEFT: 111 case ST_ATTACHMENT_BACK_LEFT: 112 case ST_ATTACHMENT_FRONT_RIGHT: 113 case ST_ATTACHMENT_BACK_RIGHT: 114 format = buffer->visual->color_format; 115 bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET; 116 break; 117 case ST_ATTACHMENT_DEPTH_STENCIL: 118 format = buffer->visual->depth_stencil_format; 119 bind = PIPE_BIND_DEPTH_STENCIL; 120 break; 121 default: 122 format = PIPE_FORMAT_NONE; 123 bind = 0; 124 break; 125 } 126 127 if (format != PIPE_FORMAT_NONE) { 128 templat.format = format; 129 templat.bind = bind; 130 buffer->textures[i] = buffer->screen->resource_create(buffer->screen, 131 &templat); 132 if (!buffer->textures[i]) 133 return FALSE; 134 } 135 } 136 137 buffer->width = width; 138 buffer->height = height; 139 buffer->mask = mask; 140 141 return TRUE; 142 } 143 144 145 /** 146 * Called by the st manager to validate the framebuffer (allocate 147 * its resources). 148 */ 149 static boolean 150 hgl_st_framebuffer_validate(struct st_context_iface *stctxi, 151 struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, 152 unsigned count, struct pipe_resource **out) 153 { 154 struct hgl_context* context; 155 struct hgl_buffer* buffer; 156 unsigned stAttachmentMask, newMask; 157 unsigned i; 158 boolean resized; 159 160 CALLED(); 161 162 context = hgl_st_context(stctxi); 163 buffer = hgl_st_framebuffer(stfbi); 164 165 //int32 width = 0; 166 //int32 height = 0; 167 //get_bitmap_size(context->bitmap, &width, &height); 168 169 // Build mask of current attachments 170 stAttachmentMask = 0; 171 for (i = 0; i < count; i++) 172 stAttachmentMask |= 1 << statts[i]; 173 174 newMask = stAttachmentMask & ~buffer->mask; 175 176 resized = (buffer->width != context->width) 177 || (buffer->height != context->height); 178 179 if (resized || newMask) { 180 boolean ret; 181 TRACE("%s: resize event. old: %d x %d; new: %d x %d\n", __func__, 182 buffer->width, buffer->height, context->width, context->height); 183 184 ret = hgl_st_framebuffer_validate_textures(stfbi, 185 context->width, context->height, stAttachmentMask); 186 187 if (!ret) 188 return ret; 189 190 // TODO: Simply update attachments 191 //if (!resized) { 192 193 //} 194 } 195 196 for (i = 0; i < count; i++) { 197 out[i] = NULL; 198 pipe_resource_reference(&out[i], buffer->textures[statts[i]]); 199 } 200 201 return TRUE; 202 } 203 204 205 static int 206 hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param) 207 { 208 CALLED(); 209 210 switch (param) { 211 case ST_MANAGER_BROKEN_INVALIDATE: 212 return 1; 213 } 214 215 return 0; 216 } 217 218 219 /** 220 * Create new framebuffer 221 */ 222 struct hgl_buffer * 223 hgl_create_st_framebuffer(struct hgl_context* context) 224 { 225 struct hgl_buffer *buffer; 226 CALLED(); 227 228 // Our requires before creating a framebuffer 229 assert(context); 230 assert(context->screen); 231 assert(context->stVisual); 232 233 buffer = CALLOC_STRUCT(hgl_buffer); 234 assert(buffer); 235 236 // calloc and configure our st_framebuffer interface 237 buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface); 238 assert(buffer->stfbi); 239 240 // Prepare our buffer 241 buffer->visual = context->stVisual; 242 buffer->screen = context->screen; 243 244 if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES)) 245 buffer->target = PIPE_TEXTURE_2D; 246 else 247 buffer->target = PIPE_TEXTURE_RECT; 248 249 // Prepare our state_tracker interface 250 buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front; 251 buffer->stfbi->validate = hgl_st_framebuffer_validate; 252 buffer->stfbi->visual = context->stVisual; 253 254 p_atomic_set(&buffer->stfbi->stamp, 1); 255 buffer->stfbi->st_manager_private = (void*)buffer; 256 257 return buffer; 258 } 259 260 261 struct st_api* 262 hgl_create_st_api() 263 { 264 CALLED(); 265 return st_gl_api_create(); 266 } 267 268 269 struct st_manager * 270 hgl_create_st_manager(struct hgl_context* context) 271 { 272 struct st_manager* manager; 273 274 CALLED(); 275 276 // Required things 277 assert(context); 278 assert(context->screen); 279 280 manager = CALLOC_STRUCT(st_manager); 281 assert(manager); 282 283 //manager->display = dpy; 284 manager->screen = context->screen; 285 manager->get_param = hgl_st_manager_get_param; 286 287 return manager; 288 } 289 290 291 void 292 hgl_destroy_st_manager(struct st_manager *manager) 293 { 294 CALLED(); 295 296 FREE(manager); 297 } 298 299 300 struct st_visual* 301 hgl_create_st_visual(ulong options) 302 { 303 struct st_visual* visual; 304 305 CALLED(); 306 307 visual = CALLOC_STRUCT(st_visual); 308 assert(visual); 309 310 // Determine color format 311 if ((options & BGL_INDEX) != 0) { 312 // Index color 313 visual->color_format = PIPE_FORMAT_B5G6R5_UNORM; 314 // TODO: Indexed color depth buffer? 315 visual->depth_stencil_format = PIPE_FORMAT_NONE; 316 } else { 317 // RGB color 318 visual->color_format = (options & BGL_ALPHA) 319 ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM; 320 // TODO: Determine additional stencil formats 321 visual->depth_stencil_format = (options & BGL_DEPTH) 322 ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE; 323 } 324 325 visual->accum_format = (options & BGL_ACCUM) 326 ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 327 328 visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 329 visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT; 330 331 if ((options & BGL_DOUBLE) != 0) { 332 visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 333 visual->render_buffer = ST_ATTACHMENT_BACK_LEFT; 334 } 335 336 #if 0 337 if ((options & BGL_STEREO) != 0) { 338 visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 339 if ((options & BGL_DOUBLE) != 0) 340 visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 341 } 342 #endif 343 344 if ((options & BGL_DEPTH) || (options & BGL_STENCIL)) 345 visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 346 347 TRACE("%s: Visual color format: %s\n", __func__, 348 util_format_name(visual->color_format)); 349 350 return visual; 351 } 352 353 354 void 355 hgl_destroy_st_visual(struct st_visual* visual) 356 { 357 CALLED(); 358 359 FREE(visual); 360 } 361