Home | History | Annotate | Download | only in hgl
      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