Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp
4565 views
1
/*
2
* Copyright 2006-2012, Haiku, Inc. All rights reserved.
3
* Distributed under the terms of the MIT License.
4
*
5
* Authors:
6
* Jérôme Duval, [email protected]
7
* Philippe Houdoin, [email protected]
8
* Artur Wyszynski, [email protected]
9
* Alexander von Gluck IV, [email protected]
10
*/
11
12
13
#include "SoftwareRenderer.h"
14
15
#include <Autolock.h>
16
#include <interface/DirectWindowPrivate.h>
17
#include <GraphicsDefs.h>
18
#include <Screen.h>
19
#include <stdio.h>
20
#include <sys/time.h>
21
#include <new>
22
23
24
#ifdef DEBUG
25
# define TRACE(x...) printf("SoftwareRenderer: " 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("SoftwareRenderer: " x)
32
33
34
extern const char* color_space_name(color_space space);
35
36
37
extern "C" _EXPORT BGLRenderer*
38
instantiate_gl_renderer(BGLView *view, ulong opts)
39
{
40
return new SoftwareRenderer(view, opts);
41
}
42
43
struct RasBuf32
44
{
45
int32 width, height, stride;
46
int32 orgX, orgY;
47
int32 *colors;
48
49
RasBuf32(int32 width, int32 height, int32 stride, int32 orgX, int32 orgY, int32 *colors):
50
width(width), height(height), stride(stride), orgX(orgX), orgY(orgY), colors(colors)
51
{}
52
53
RasBuf32(BBitmap *bmp)
54
{
55
width = bmp->Bounds().IntegerWidth() + 1;
56
height = bmp->Bounds().IntegerHeight() + 1;
57
stride = bmp->BytesPerRow()/4;
58
orgX = 0;
59
orgY = 0;
60
colors = (int32*)bmp->Bits();
61
}
62
63
RasBuf32(direct_buffer_info *info)
64
{
65
width = 0x7fffffff;
66
height = 0x7fffffff;
67
stride = info->bytes_per_row/4;
68
orgX = 0;
69
orgY = 0;
70
colors = (int32*)info->bits;
71
}
72
73
void ClipSize(int32 x, int32 y, int32 w, int32 h)
74
{
75
if (x < 0) {w += x; x = 0;}
76
if (y < 0) {h += y; y = 0;}
77
if (x + w > width) {w = width - x;}
78
if (y + h > height) {h = height - y;}
79
if ((w > 0) && (h > 0)) {
80
colors += y*stride + x;
81
width = w;
82
height = h;
83
} else {
84
width = 0; height = 0; colors = NULL;
85
}
86
if (x + orgX > 0) {orgX += x;} else {orgX = 0;}
87
if (y + orgY > 0) {orgY += y;} else {orgY = 0;}
88
}
89
90
void ClipRect(int32 l, int32 t, int32 r, int32 b)
91
{
92
ClipSize(l, t, r - l, b - t);
93
}
94
95
void Shift(int32 dx, int32 dy)
96
{
97
orgX += dx;
98
orgY += dy;
99
}
100
101
void Clear(int32 color)
102
{
103
RasBuf32 dst = *this;
104
dst.stride -= dst.width;
105
for (; dst.height > 0; dst.height--) {
106
for (int32 i = dst.width; i > 0; i--)
107
*dst.colors++ = color;
108
dst.colors += dst.stride;
109
}
110
}
111
112
void Blit(RasBuf32 src)
113
{
114
RasBuf32 dst = *this;
115
int32 x, y;
116
x = src.orgX - orgX;
117
y = src.orgY - orgY;
118
dst.ClipSize(x, y, src.width, src.height);
119
src.ClipSize(-x, -y, width, height);
120
for (; dst.height > 0; dst.height--) {
121
memcpy(dst.colors, src.colors, 4*dst.width);
122
dst.colors += dst.stride;
123
src.colors += src.stride;
124
}
125
}
126
};
127
128
SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options)
129
:
130
BGLRenderer(view, options),
131
fDirectModeEnabled(false),
132
fInfo(NULL),
133
fInfoLocker("info locker"),
134
fOptions(options),
135
fColorSpace(B_NO_COLOR_SPACE)
136
{
137
CALLED();
138
139
// Initialize the "Haiku Software GL Pipe"
140
time_t beg;
141
time_t end;
142
beg = time(NULL);
143
fContextObj = new GalliumContext(options);
144
end = time(NULL);
145
TRACE("Haiku Software GL Pipe initialization time: %f.\n",
146
difftime(end, beg));
147
148
BRect b = view->Bounds();
149
fColorSpace = BScreen(view->Window()).ColorSpace();
150
TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
151
152
fWidth = (GLint)b.IntegerWidth();
153
fHeight = (GLint)b.IntegerHeight();
154
155
// Initialize the first "Haiku Software GL Pipe" context
156
beg = time(NULL);
157
fContextID = fContextObj->CreateContext(this);
158
end = time(NULL);
159
160
if (fContextID < 0)
161
ERROR("%s: There was an error creating the context!\n", __func__);
162
else {
163
TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
164
__func__, difftime(end, beg));
165
}
166
167
if (!fContextObj->GetCurrentContext())
168
LockGL();
169
}
170
171
172
SoftwareRenderer::~SoftwareRenderer()
173
{
174
CALLED();
175
176
if (fContextObj)
177
delete fContextObj;
178
}
179
180
181
void
182
SoftwareRenderer::LockGL()
183
{
184
// CALLED();
185
BGLRenderer::LockGL();
186
187
color_space cs = BScreen(GLView()->Window()).ColorSpace();
188
189
{
190
BAutolock lock(fInfoLocker);
191
if (fDirectModeEnabled && fInfo != NULL) {
192
fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
193
fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
194
}
195
196
fContextObj->Validate(fWidth, fHeight);
197
fColorSpace = cs;
198
}
199
200
// do not hold fInfoLocker here to avoid deadlock
201
fContextObj->SetCurrentContext(true, fContextID);
202
}
203
204
205
void
206
SoftwareRenderer::UnlockGL()
207
{
208
// CALLED();
209
if ((fOptions & BGL_DOUBLE) == 0) {
210
SwapBuffers();
211
}
212
fContextObj->SetCurrentContext(false, fContextID);
213
BGLRenderer::UnlockGL();
214
}
215
216
217
void
218
SoftwareRenderer::Display(BBitmap *bitmap, BRect *updateRect)
219
{
220
// CALLED();
221
222
if (!fDirectModeEnabled) {
223
// TODO: avoid timeout
224
if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
225
GLView()->DrawBitmap(bitmap, B_ORIGIN);
226
GLView()->UnlockLooper();
227
}
228
} else {
229
BAutolock lock(fInfoLocker);
230
if (fInfo != NULL) {
231
RasBuf32 srcBuf(bitmap);
232
RasBuf32 dstBuf(fInfo);
233
for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
234
clipping_rect *clip = &fInfo->clip_list[i];
235
RasBuf32 dstClip = dstBuf;
236
dstClip.ClipRect(clip->left, clip->top, clip->right + 1, clip->bottom + 1);
237
dstClip.Shift(-fInfo->window_bounds.left, -fInfo->window_bounds.top);
238
dstClip.Blit(srcBuf);
239
}
240
}
241
}
242
}
243
244
245
void
246
SoftwareRenderer::SwapBuffers(bool vsync)
247
{
248
BScreen screen(GLView()->Window());
249
fContextObj->SwapBuffers(fContextID);
250
fContextObj->Validate(fWidth, fHeight);
251
if (vsync)
252
screen.WaitForRetrace();
253
}
254
255
void
256
SoftwareRenderer::Draw(BRect updateRect)
257
{
258
// CALLED();
259
fContextObj->Draw(fContextID, updateRect);
260
}
261
262
263
status_t
264
SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
265
{
266
CALLED();
267
268
// TODO: implement
269
return B_ERROR;
270
}
271
272
273
status_t
274
SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
275
{
276
CALLED();
277
278
// TODO: implement
279
return B_ERROR;
280
}
281
282
283
void
284
SoftwareRenderer::EnableDirectMode(bool enabled)
285
{
286
fDirectModeEnabled = enabled;
287
}
288
289
290
void
291
SoftwareRenderer::DirectConnected(direct_buffer_info *info)
292
{
293
// CALLED();
294
BAutolock lock(fInfoLocker);
295
if (info) {
296
if (!fInfo) {
297
fInfo = (direct_buffer_info *)calloc(1,
298
DIRECT_BUFFER_INFO_AREA_SIZE);
299
}
300
memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
301
} else if (fInfo) {
302
free(fInfo);
303
fInfo = NULL;
304
}
305
}
306
307
308
void
309
SoftwareRenderer::FrameResized(float width, float height)
310
{
311
TRACE("%s: %f x %f\n", __func__, width, height);
312
313
BAutolock lock(fInfoLocker);
314
fWidth = (GLuint)width;
315
fHeight = (GLuint)height;
316
}
317
318