1/**************************************************************************
2 *
3 * Copyright 2009 Artur Wyszynski <harakash@gmail.com>
4 * Copyright 2013-2014 Alexander von Gluck IV <kallisti5@unixzen.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28#include <stdio.h>
29
30#include "pipe/p_compiler.h"
31#include "pipe/p_defines.h"
32#include "pipe/p_format.h"
33#include "util/u_inlines.h"
34#include "util/format/u_format.h"
35#include "util/u_math.h"
36#include "util/u_memory.h"
37#include "frontend/api.h"
38#include "frontend/sw_winsys.h"
39
40#include "hgl_sw_winsys.h"
41
42#include <Bitmap.h>
43#include <OS.h>
44
45#ifdef DEBUG
46#   define TRACE(x...) printf("hgl:winsys: " x)
47#   define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
48#else
49#   define TRACE(x...)
50#   define CALLED()
51#endif
52#define ERROR(x...) printf("hgl:winsys: " x)
53
54
55struct haiku_displaytarget
56{
57	enum pipe_format format;
58	color_space colorSpace;
59
60	unsigned width;
61	unsigned height;
62	unsigned stride;
63
64	unsigned size;
65
66	void* data;
67	BBitmap* bitmap;
68};
69
70
71// Cast
72static inline struct haiku_displaytarget*
73hgl_sw_displaytarget(struct sw_displaytarget* target)
74{
75	return (struct haiku_displaytarget *)target;
76}
77
78
79static void
80hgl_winsys_destroy(struct sw_winsys* winsys)
81{
82	FREE(winsys);
83}
84
85
86static bool
87hgl_winsys_is_displaytarget_format_supported(struct sw_winsys* winsys,
88	unsigned textureUsage, enum pipe_format format)
89{
90	// TODO STUB
91	return true;
92}
93
94static color_space
95hgl_winsys_convert_cs(enum pipe_format format)
96{
97	// TODO: B_RGB24, B_RGB16, B_RGB15?
98	switch(format) {
99		case PIPE_FORMAT_B5G6R5_UNORM:
100			return B_CMAP8;
101		case PIPE_FORMAT_A8B8G8R8_UNORM:
102		case PIPE_FORMAT_X8B8G8R8_UNORM:
103		default:
104			return B_RGB32;
105	}
106}
107
108static struct sw_displaytarget*
109hgl_winsys_displaytarget_create(struct sw_winsys* winsys,
110	unsigned textureUsage, enum pipe_format format, unsigned width,
111	unsigned height, unsigned alignment, const void *front_private,
112	unsigned* stride)
113{
114	struct haiku_displaytarget* haikuDisplayTarget
115		= CALLOC_STRUCT(haiku_displaytarget);
116	assert(haikuDisplayTarget);
117
118	TRACE("%s: %d x %d\n", __func__, width, height);
119
120	haikuDisplayTarget->colorSpace = hgl_winsys_convert_cs(format);
121	haikuDisplayTarget->format = format;
122	haikuDisplayTarget->width = width;
123	haikuDisplayTarget->height = height;
124
125	size_t formatStride = util_format_get_stride(format, width);
126	unsigned blockSize = util_format_get_nblocksy(format, height);
127
128	haikuDisplayTarget->stride = align(formatStride, alignment);
129	haikuDisplayTarget->size = haikuDisplayTarget->stride * blockSize;
130
131	if (textureUsage & PIPE_BIND_DISPLAY_TARGET) {
132		haikuDisplayTarget->data = NULL;
133		haikuDisplayTarget->bitmap = new BBitmap(
134			BRect(0, 0, width - 1, height - 1),
135			haikuDisplayTarget->colorSpace,
136			haikuDisplayTarget->stride);
137	} else {
138		haikuDisplayTarget->data
139			= align_malloc(haikuDisplayTarget->size, alignment);
140
141		haikuDisplayTarget->bitmap = NULL;
142	}
143
144	*stride = haikuDisplayTarget->stride;
145
146	// Cast to ghost sw_displaytarget type
147	return (struct sw_displaytarget*)haikuDisplayTarget;
148}
149
150
151static void
152hgl_winsys_displaytarget_destroy(struct sw_winsys* winsys,
153	struct sw_displaytarget* displayTarget)
154{
155	struct haiku_displaytarget* haikuDisplayTarget
156		= hgl_sw_displaytarget(displayTarget);
157
158	if (!haikuDisplayTarget)
159		return;
160
161	if (haikuDisplayTarget->data != NULL)
162		align_free(haikuDisplayTarget->data);
163
164	if (haikuDisplayTarget->bitmap != NULL)
165		delete haikuDisplayTarget->bitmap;
166
167	FREE(haikuDisplayTarget);
168}
169
170
171static struct sw_displaytarget*
172hgl_winsys_displaytarget_from_handle(struct sw_winsys* winsys,
173	const struct pipe_resource* templat, struct winsys_handle* whandle,
174	unsigned* stride)
175{
176	return NULL;
177}
178
179
180static bool
181hgl_winsys_displaytarget_get_handle(struct sw_winsys* winsys,
182	struct sw_displaytarget* displayTarget, struct winsys_handle* whandle)
183{
184	return false;
185}
186
187
188static void*
189hgl_winsys_displaytarget_map(struct sw_winsys* winsys,
190	struct sw_displaytarget* displayTarget, unsigned flags)
191{
192	struct haiku_displaytarget* haikuDisplayTarget
193		= hgl_sw_displaytarget(displayTarget);
194
195	if (haikuDisplayTarget->bitmap != NULL)
196		return haikuDisplayTarget->bitmap->Bits();
197
198	return haikuDisplayTarget->data;
199}
200
201
202static void
203hgl_winsys_displaytarget_unmap(struct sw_winsys* winsys,
204	struct sw_displaytarget* displayTarget)
205{
206	return;
207}
208
209
210static void
211hgl_winsys_displaytarget_display(struct sw_winsys* winsys,
212	struct sw_displaytarget* displayTarget, void* contextPrivate,
213	struct pipe_box *box)
214{
215	assert(contextPrivate);
216
217	struct haiku_displaytarget* haikuDisplayTarget
218		= hgl_sw_displaytarget(displayTarget);
219
220	HGLWinsysContext *context = (HGLWinsysContext*)contextPrivate;
221	context->Display(haikuDisplayTarget->bitmap, NULL);
222}
223
224
225struct sw_winsys*
226hgl_create_sw_winsys()
227{
228	struct sw_winsys* winsys = CALLOC_STRUCT(sw_winsys);
229
230	if (!winsys)
231		return NULL;
232
233	// Attach winsys hooks for Haiku
234	winsys->destroy = hgl_winsys_destroy;
235	winsys->is_displaytarget_format_supported
236		= hgl_winsys_is_displaytarget_format_supported;
237	winsys->displaytarget_create = hgl_winsys_displaytarget_create;
238	winsys->displaytarget_from_handle = hgl_winsys_displaytarget_from_handle;
239	winsys->displaytarget_get_handle = hgl_winsys_displaytarget_get_handle;
240	winsys->displaytarget_map = hgl_winsys_displaytarget_map;
241	winsys->displaytarget_unmap = hgl_winsys_displaytarget_unmap;
242	winsys->displaytarget_display = hgl_winsys_displaytarget_display;
243	winsys->displaytarget_destroy = hgl_winsys_displaytarget_destroy;
244
245	return winsys;
246}
247