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@gmail.com 7 * Alexander von Gluck IV, kallisti5@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 35static inline struct hgl_context* 36hgl_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 47static inline struct hgl_buffer* 48hgl_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 58static boolean 59hgl_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 mtx_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 80static boolean 81hgl_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 */ 149static boolean 150hgl_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 pipe_resource_reference(&out[i], buffer->textures[statts[i]]); 198 199 return TRUE; 200} 201 202 203static int 204hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param) 205{ 206 CALLED(); 207 208 switch (param) { 209 case ST_MANAGER_BROKEN_INVALIDATE: 210 return 1; 211 } 212 213 return 0; 214} 215 216 217/** 218 * Create new framebuffer 219 */ 220struct hgl_buffer * 221hgl_create_st_framebuffer(struct hgl_context* context) 222{ 223 struct hgl_buffer *buffer; 224 CALLED(); 225 226 // Our requires before creating a framebuffer 227 assert(context); 228 assert(context->screen); 229 assert(context->stVisual); 230 231 buffer = CALLOC_STRUCT(hgl_buffer); 232 assert(buffer); 233 234 // calloc and configure our st_framebuffer interface 235 buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface); 236 assert(buffer->stfbi); 237 238 // Prepare our buffer 239 buffer->visual = context->stVisual; 240 buffer->screen = context->screen; 241 242 if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES)) 243 buffer->target = PIPE_TEXTURE_2D; 244 else 245 buffer->target = PIPE_TEXTURE_RECT; 246 247 // Prepare our state_tracker interface 248 buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front; 249 buffer->stfbi->validate = hgl_st_framebuffer_validate; 250 buffer->stfbi->visual = context->stVisual; 251 252 p_atomic_set(&buffer->stfbi->stamp, 1); 253 buffer->stfbi->st_manager_private = (void*)buffer; 254 255 return buffer; 256} 257 258 259struct st_api* 260hgl_create_st_api() 261{ 262 CALLED(); 263 return st_gl_api_create(); 264} 265 266 267struct st_manager * 268hgl_create_st_manager(struct hgl_context* context) 269{ 270 struct st_manager* manager; 271 272 CALLED(); 273 274 // Required things 275 assert(context); 276 assert(context->screen); 277 278 manager = CALLOC_STRUCT(st_manager); 279 assert(manager); 280 281 //manager->display = dpy; 282 manager->screen = context->screen; 283 manager->get_param = hgl_st_manager_get_param; 284 285 return manager; 286} 287 288 289void 290hgl_destroy_st_manager(struct st_manager *manager) 291{ 292 CALLED(); 293 294 FREE(manager); 295} 296 297 298struct st_visual* 299hgl_create_st_visual(ulong options) 300{ 301 struct st_visual* visual; 302 303 CALLED(); 304 305 visual = CALLOC_STRUCT(st_visual); 306 assert(visual); 307 308 // Determine color format 309 if ((options & BGL_INDEX) != 0) { 310 // Index color 311 visual->color_format = PIPE_FORMAT_B5G6R5_UNORM; 312 // TODO: Indexed color depth buffer? 313 visual->depth_stencil_format = PIPE_FORMAT_NONE; 314 } else { 315 // RGB color 316 visual->color_format = (options & BGL_ALPHA) 317 ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM; 318 // TODO: Determine additional stencil formats 319 visual->depth_stencil_format = (options & BGL_DEPTH) 320 ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE; 321 } 322 323 visual->accum_format = (options & BGL_ACCUM) 324 ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 325 326 visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 327 visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT; 328 329 if ((options & BGL_DOUBLE) != 0) { 330 visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 331 visual->render_buffer = ST_ATTACHMENT_BACK_LEFT; 332 } 333 334 #if 0 335 if ((options & BGL_STEREO) != 0) { 336 visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 337 if ((options & BGL_DOUBLE) != 0) 338 visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 339 } 340 #endif 341 342 if ((options & BGL_DEPTH) || (options & BGL_STENCIL)) 343 visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 344 345 TRACE("%s: Visual color format: %s\n", __func__, 346 util_format_name(visual->color_format)); 347 348 return visual; 349} 350 351 352void 353hgl_destroy_st_visual(struct st_visual* visual) 354{ 355 CALLED(); 356 357 FREE(visual); 358} 359