• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
35 static inline struct hgl_context*
hgl_st_context(struct st_context_iface * stctxi)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*
hgl_st_framebuffer(struct st_framebuffer_iface * stfbi)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
hgl_st_framebuffer_flush_front(struct st_context_iface * stctxi,struct st_framebuffer_iface * stfbi,enum st_attachment_type statt)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 	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 
80 static boolean
hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface * stfbi,unsigned width,unsigned height,unsigned mask)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
hgl_st_framebuffer_validate(struct st_context_iface * stctxi,struct st_framebuffer_iface * stfbi,const enum st_attachment_type * statts,unsigned count,struct pipe_resource ** out)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 		pipe_resource_reference(&out[i], buffer->textures[statts[i]]);
198 
199 	return TRUE;
200 }
201 
202 
203 static int
hgl_st_manager_get_param(struct st_manager * smapi,enum st_manager_param param)204 hgl_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  */
220 struct hgl_buffer *
hgl_create_st_framebuffer(struct hgl_context * context)221 hgl_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 
259 struct st_api*
hgl_create_st_api()260 hgl_create_st_api()
261 {
262 	CALLED();
263 	return st_gl_api_create();
264 }
265 
266 
267 struct st_manager *
hgl_create_st_manager(struct hgl_context * context)268 hgl_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 
289 void
hgl_destroy_st_manager(struct st_manager * manager)290 hgl_destroy_st_manager(struct st_manager *manager)
291 {
292 	CALLED();
293 
294 	FREE(manager);
295 }
296 
297 
298 struct st_visual*
hgl_create_st_visual(ulong options)299 hgl_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 
352 void
hgl_destroy_st_visual(struct st_visual * visual)353 hgl_destroy_st_visual(struct st_visual* visual)
354 {
355 	CALLED();
356 
357 	FREE(visual);
358 }
359