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