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 	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
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 		out[i] = NULL;
198 		pipe_resource_reference(&out[i], buffer->textures[statts[i]]);
199 	}
200 
201 	return TRUE;
202 }
203 
204 
205 static int
hgl_st_manager_get_param(struct st_manager * smapi,enum st_manager_param param)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 *
hgl_create_st_framebuffer(struct hgl_context * context)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*
hgl_create_st_api()262 hgl_create_st_api()
263 {
264 	CALLED();
265 	return st_gl_api_create();
266 }
267 
268 
269 struct st_manager *
hgl_create_st_manager(struct hgl_context * context)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
hgl_destroy_st_manager(struct st_manager * manager)292 hgl_destroy_st_manager(struct st_manager *manager)
293 {
294 	CALLED();
295 
296 	FREE(manager);
297 }
298 
299 
300 struct st_visual*
hgl_create_st_visual(ulong options)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
hgl_destroy_st_visual(struct st_visual * visual)355 hgl_destroy_st_visual(struct st_visual* visual)
356 {
357 	CALLED();
358 
359 	FREE(visual);
360 }
361