Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/hgl/GLView.cpp
4558 views
1
/*
2
* Copyright 2006-2012, Haiku. 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
* Stefano Ceccherini, [email protected]
9
*/
10
11
#include <kernel/image.h>
12
13
#include <GLView.h>
14
15
#include <assert.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include <DirectWindow.h>
21
#include "GLRenderer.h"
22
23
#include <private/interface/DirectWindowPrivate.h>
24
#include "GLRendererRoster.h"
25
26
#include "glapi/glapi.h"
27
28
struct glview_direct_info {
29
direct_buffer_info* direct_info;
30
bool direct_connected;
31
bool enable_direct_mode;
32
33
glview_direct_info();
34
~glview_direct_info();
35
};
36
37
38
BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
39
ulong options)
40
:
41
BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
42
fGc(NULL),
43
fOptions(options),
44
fDitherCount(0),
45
fDrawLock("BGLView draw lock"),
46
fDisplayLock("BGLView display lock"),
47
fClipInfo(NULL),
48
fRenderer(NULL),
49
fDitherMap(NULL)
50
{
51
fRenderer = GLRendererRoster::Roster()->GetRenderer(this, options);
52
}
53
54
55
BGLView::~BGLView()
56
{
57
delete fClipInfo;
58
if (fRenderer)
59
fRenderer->Release();
60
}
61
62
63
void
64
BGLView::LockGL()
65
{
66
// TODO: acquire the OpenGL API lock it on this glview
67
68
fDisplayLock.Lock();
69
if (fRenderer != NULL && fDisplayLock.CountLocks() == 1)
70
fRenderer->LockGL();
71
}
72
73
74
void
75
BGLView::UnlockGL()
76
{
77
thread_id lockerThread = fDisplayLock.LockingThread();
78
thread_id callerThread = find_thread(NULL);
79
80
if (lockerThread != B_ERROR && lockerThread != callerThread) {
81
printf("UnlockGL is called from wrong thread, lockerThread: %d, callerThread: %d\n",
82
(int)lockerThread, (int)callerThread);
83
debugger("[!]");
84
}
85
86
if (fRenderer != NULL && fDisplayLock.CountLocks() == 1)
87
fRenderer->UnlockGL();
88
fDisplayLock.Unlock();
89
90
// TODO: release the GL API lock to others glviews
91
}
92
93
94
void
95
BGLView::SwapBuffers()
96
{
97
SwapBuffers(false);
98
}
99
100
101
void
102
BGLView::SwapBuffers(bool vSync)
103
{
104
if (fRenderer) {
105
_LockDraw();
106
fRenderer->SwapBuffers(vSync);
107
_UnlockDraw();
108
}
109
}
110
111
112
BView*
113
BGLView::EmbeddedView()
114
{
115
return NULL;
116
}
117
118
119
void*
120
BGLView::GetGLProcAddress(const char* procName)
121
{
122
return (void*)_glapi_get_proc_address(procName);
123
}
124
125
126
status_t
127
BGLView::CopyPixelsOut(BPoint source, BBitmap* dest)
128
{
129
if (!fRenderer)
130
return B_ERROR;
131
132
if (!dest || !dest->Bounds().IsValid())
133
return B_BAD_VALUE;
134
135
return fRenderer->CopyPixelsOut(source, dest);
136
}
137
138
139
status_t
140
BGLView::CopyPixelsIn(BBitmap* source, BPoint dest)
141
{
142
if (!fRenderer)
143
return B_ERROR;
144
145
if (!source || !source->Bounds().IsValid())
146
return B_BAD_VALUE;
147
148
return fRenderer->CopyPixelsIn(source, dest);
149
}
150
151
152
/*! Mesa's GLenum is not ulong but uint, so we can't use GLenum
153
without breaking this method signature.
154
Instead, we have to use the effective BeOS's SGI OpenGL GLenum type:
155
unsigned long.
156
*/
157
void
158
BGLView::ErrorCallback(unsigned long errorCode)
159
{
160
char msg[32];
161
sprintf(msg, "GL: Error code $%04lx.", errorCode);
162
// TODO: under BeOS R5, it call debugger(msg);
163
fprintf(stderr, "%s\n", msg);
164
}
165
166
167
void
168
BGLView::Draw(BRect updateRect)
169
{
170
if (fRenderer) {
171
if (!fClipInfo || !fClipInfo->enable_direct_mode)
172
fRenderer->Draw(updateRect);
173
return;
174
}
175
// TODO: auto-size and center the string
176
MovePenTo(8, 32);
177
DrawString("No OpenGL renderer available!");
178
}
179
180
181
void
182
BGLView::AttachedToWindow()
183
{
184
BView::AttachedToWindow();
185
186
fBounds = Bounds();
187
for (BView* view = this; view != NULL; view = view->Parent())
188
view->ConvertToParent(&fBounds);
189
190
if (fRenderer != NULL) {
191
// Jackburton: The following code was commented because it doesn't look
192
// good in "direct" mode:
193
// when the window is moved, the app_server doesn't paint the view's
194
// background, and the stuff behind the window itself shows up.
195
// Setting the view color to black, instead, looks a bit more elegant.
196
#if 0
197
// Don't paint white window background when resized
198
SetViewColor(B_TRANSPARENT_32_BIT);
199
#else
200
SetViewColor(0, 0, 0);
201
#endif
202
203
// Set default OpenGL viewport:
204
LockGL();
205
glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
206
UnlockGL();
207
fRenderer->FrameResized(Bounds().IntegerWidth(),
208
Bounds().IntegerHeight());
209
210
if (fClipInfo) {
211
fRenderer->DirectConnected(fClipInfo->direct_info);
212
fRenderer->EnableDirectMode(fClipInfo->enable_direct_mode);
213
}
214
215
return;
216
}
217
218
fprintf(stderr, "no renderer found! \n");
219
220
// No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
221
// context
222
SetFont(be_bold_font);
223
// SetFontSize(16);
224
}
225
226
227
void
228
BGLView::AllAttached()
229
{
230
BView::AllAttached();
231
}
232
233
234
void
235
BGLView::DetachedFromWindow()
236
{
237
BView::DetachedFromWindow();
238
}
239
240
241
void
242
BGLView::AllDetached()
243
{
244
BView::AllDetached();
245
}
246
247
248
void
249
BGLView::FrameResized(float width, float height)
250
{
251
fBounds = Bounds();
252
for (BView* v = this; v; v = v->Parent())
253
v->ConvertToParent(&fBounds);
254
255
if (fRenderer) {
256
//_LockDraw();
257
fRenderer->FrameResized(width, height);
258
//_UnlockDraw();
259
}
260
261
BView::FrameResized(width, height);
262
}
263
264
265
status_t
266
BGLView::Perform(perform_code d, void* arg)
267
{
268
return BView::Perform(d, arg);
269
}
270
271
272
status_t
273
BGLView::Archive(BMessage* data, bool deep) const
274
{
275
return BView::Archive(data, deep);
276
}
277
278
279
void
280
BGLView::MessageReceived(BMessage* msg)
281
{
282
BView::MessageReceived(msg);
283
}
284
285
286
void
287
BGLView::SetResizingMode(uint32 mode)
288
{
289
BView::SetResizingMode(mode);
290
}
291
292
293
void
294
BGLView::GetPreferredSize(float* _width, float* _height)
295
{
296
if (_width)
297
*_width = 0;
298
if (_height)
299
*_height = 0;
300
}
301
302
303
void
304
BGLView::Show()
305
{
306
BView::Show();
307
}
308
309
310
void
311
BGLView::Hide()
312
{
313
BView::Hide();
314
}
315
316
317
BHandler*
318
BGLView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
319
int32 form, const char* property)
320
{
321
return BView::ResolveSpecifier(msg, index, specifier, form, property);
322
}
323
324
325
status_t
326
BGLView::GetSupportedSuites(BMessage* data)
327
{
328
return BView::GetSupportedSuites(data);
329
}
330
331
332
void
333
BGLView::DirectConnected(direct_buffer_info* info)
334
{
335
printf("BGLView::DirectConnected\n");
336
if (fClipInfo == NULL) {
337
fClipInfo = new (std::nothrow) glview_direct_info();
338
if (fClipInfo == NULL)
339
return;
340
}
341
342
direct_buffer_info* localInfo = fClipInfo->direct_info;
343
344
_LockDraw();
345
switch (info->buffer_state & B_DIRECT_MODE_MASK) {
346
case B_DIRECT_START:
347
fClipInfo->direct_connected = true;
348
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
349
break;
350
351
case B_DIRECT_MODIFY:
352
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
353
break;
354
355
case B_DIRECT_STOP:
356
fClipInfo->direct_connected = false;
357
break;
358
}
359
360
if (fRenderer)
361
_CallDirectConnected();
362
363
_UnlockDraw();
364
}
365
366
367
void
368
BGLView::EnableDirectMode(bool enabled)
369
{
370
printf("BGLView::EnableDirectMode: %d\n", (int)enabled);
371
if (fRenderer)
372
fRenderer->EnableDirectMode(enabled);
373
if (fClipInfo == NULL) {
374
fClipInfo = new (std::nothrow) glview_direct_info();
375
if (fClipInfo == NULL)
376
return;
377
}
378
379
fClipInfo->enable_direct_mode = enabled;
380
}
381
382
383
void
384
BGLView::_LockDraw()
385
{
386
if (!fClipInfo || !fClipInfo->enable_direct_mode)
387
return;
388
389
fDrawLock.Lock();
390
}
391
392
393
void
394
BGLView::_UnlockDraw()
395
{
396
if (!fClipInfo || !fClipInfo->enable_direct_mode)
397
return;
398
399
fDrawLock.Unlock();
400
}
401
402
403
void
404
BGLView::_CallDirectConnected()
405
{
406
if (!fClipInfo || !fClipInfo->direct_connected) {
407
fRenderer->DirectConnected(NULL);
408
return;
409
}
410
411
direct_buffer_info* localInfo = fClipInfo->direct_info;
412
direct_buffer_info* info = (direct_buffer_info*)malloc(
413
DIRECT_BUFFER_INFO_AREA_SIZE);
414
if (info == NULL)
415
return;
416
417
memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE);
418
419
// Collect the rects into a BRegion, then clip to the view's bounds
420
BRegion region;
421
for (uint32 c = 0; c < localInfo->clip_list_count; c++)
422
region.Include(localInfo->clip_list[c]);
423
BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left,
424
localInfo->window_bounds.top);
425
info->window_bounds = boundsRegion.RectAtInt(0);
426
// window_bounds are now view bounds
427
region.IntersectWith(&boundsRegion);
428
429
info->clip_list_count = region.CountRects();
430
info->clip_bounds = region.FrameInt();
431
432
for (uint32 c = 0; c < info->clip_list_count; c++)
433
info->clip_list[c] = region.RectAtInt(c);
434
fRenderer->DirectConnected(info);
435
free(info);
436
}
437
438
439
//---- virtual reserved methods ----------
440
441
442
void BGLView::_ReservedGLView1() {}
443
void BGLView::_ReservedGLView2() {}
444
void BGLView::_ReservedGLView3() {}
445
void BGLView::_ReservedGLView4() {}
446
void BGLView::_ReservedGLView5() {}
447
void BGLView::_ReservedGLView6() {}
448
void BGLView::_ReservedGLView7() {}
449
void BGLView::_ReservedGLView8() {}
450
451
452
// #pragma mark -
453
454
455
// BeOS compatibility: contrary to others BView's contructors,
456
// BGLView one wants a non-const name argument.
457
BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
458
ulong options)
459
:
460
BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
461
fGc(NULL),
462
fOptions(options),
463
fDitherCount(0),
464
fDrawLock("BGLView draw lock"),
465
fDisplayLock("BGLView display lock"),
466
fClipInfo(NULL),
467
fRenderer(NULL),
468
fDitherMap(NULL)
469
{
470
fRenderer = GLRendererRoster::Roster()->GetRenderer(this, options);
471
}
472
473
474
#if 0
475
// TODO: implement BGLScreen class...
476
477
478
BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options,
479
status_t* error, bool debug)
480
:
481
BWindowScreen(name, screenMode, error, debug)
482
{
483
}
484
485
486
BGLScreen::~BGLScreen()
487
{
488
}
489
490
491
void
492
BGLScreen::LockGL()
493
{
494
}
495
496
497
void
498
BGLScreen::UnlockGL()
499
{
500
}
501
502
503
void
504
BGLScreen::SwapBuffers()
505
{
506
}
507
508
509
void
510
BGLScreen::ErrorCallback(unsigned long errorCode)
511
{
512
// Mesa's GLenum is not ulong but uint!
513
char msg[32];
514
sprintf(msg, "GL: Error code $%04lx.", errorCode);
515
// debugger(msg);
516
fprintf(stderr, "%s\n", msg);
517
return;
518
}
519
520
521
void
522
BGLScreen::ScreenConnected(bool enabled)
523
{
524
}
525
526
527
void
528
BGLScreen::FrameResized(float width, float height)
529
{
530
return BWindowScreen::FrameResized(width, height);
531
}
532
533
534
status_t
535
BGLScreen::Perform(perform_code d, void* arg)
536
{
537
return BWindowScreen::Perform(d, arg);
538
}
539
540
541
status_t
542
BGLScreen::Archive(BMessage* data, bool deep) const
543
{
544
return BWindowScreen::Archive(data, deep);
545
}
546
547
548
void
549
BGLScreen::MessageReceived(BMessage* msg)
550
{
551
BWindowScreen::MessageReceived(msg);
552
}
553
554
555
void
556
BGLScreen::Show()
557
{
558
BWindowScreen::Show();
559
}
560
561
562
void
563
BGLScreen::Hide()
564
{
565
BWindowScreen::Hide();
566
}
567
568
569
BHandler*
570
BGLScreen::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
571
int32 form, const char* property)
572
{
573
return BWindowScreen::ResolveSpecifier(msg, index, specifier,
574
form, property);
575
}
576
577
578
status_t
579
BGLScreen::GetSupportedSuites(BMessage* data)
580
{
581
return BWindowScreen::GetSupportedSuites(data);
582
}
583
584
585
//---- virtual reserved methods ----------
586
587
void BGLScreen::_ReservedGLScreen1() {}
588
void BGLScreen::_ReservedGLScreen2() {}
589
void BGLScreen::_ReservedGLScreen3() {}
590
void BGLScreen::_ReservedGLScreen4() {}
591
void BGLScreen::_ReservedGLScreen5() {}
592
void BGLScreen::_ReservedGLScreen6() {}
593
void BGLScreen::_ReservedGLScreen7() {}
594
void BGLScreen::_ReservedGLScreen8() {}
595
#endif
596
597
598
const char* color_space_name(color_space space)
599
{
600
#define C2N(a) case a: return #a
601
602
switch (space) {
603
C2N(B_RGB24);
604
C2N(B_RGB32);
605
C2N(B_RGBA32);
606
C2N(B_RGB32_BIG);
607
C2N(B_RGBA32_BIG);
608
C2N(B_GRAY8);
609
C2N(B_GRAY1);
610
C2N(B_RGB16);
611
C2N(B_RGB15);
612
C2N(B_RGBA15);
613
C2N(B_CMAP8);
614
default:
615
return "Unknown!";
616
};
617
618
#undef C2N
619
};
620
621
622
glview_direct_info::glview_direct_info()
623
{
624
// TODO: See direct_window_data() in app_server's ServerWindow.cpp
625
direct_info = (direct_buffer_info*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE);
626
direct_connected = false;
627
enable_direct_mode = false;
628
}
629
630
631
glview_direct_info::~glview_direct_info()
632
{
633
free(direct_info);
634
}
635
636
637