VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp@ 79767

Last change on this file since 79767 was 78375, checked in by vboxsync, 6 years ago

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/* $Id: server_rpw.cpp 78375 2019-05-03 21:51:02Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Read Pixels worker
5 */
6
7/*
8 * Copyright (C) 2010-2019 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "server.h"
19#include "cr_string.h"
20#include "cr_mem.h"
21#include "cr_vreg.h"
22#include "render/renderspu.h"
23
24static void crServerRpwWorkerGpuSubmit(PRTLISTNODE pWorkList)
25{
26 CR_SERVER_RPW_ENTRY *pCurEntry;
27 RTListForEach(pWorkList, pCurEntry, CR_SERVER_RPW_ENTRY, WorkerWorkEntry)
28 {
29 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, CR_SERVER_RPW_ENTRY_TEX(pCurEntry, Worker));
30
31 if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry))
32 {
33 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, CR_SERVER_RPW_ENTRY_PBO_CUR(pCurEntry));
34 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
35 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
36 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
37 CR_SERVER_RPW_ENTRY_PBO_FLIP(pCurEntry);
38 }
39 else
40 {
41 void *pvData = crAlloc(4*pCurEntry->Size.cx*pCurEntry->Size.cy);
42 if (pvData)
43 {
44 cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pvData);
45
46 pCurEntry->pfnData(pCurEntry, pvData);
47
48 crFree(pvData);
49 }
50 else
51 {
52 crWarning("crAlloc failed");
53 }
54 }
55
56 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, 0);
57 }
58}
59
60static void crServerRpwWorkerGpuComplete(PRTLISTNODE pGpuSubmitedList)
61{
62 CR_SERVER_RPW_ENTRY *pCurEntry;
63 RTListForEach(pGpuSubmitedList, pCurEntry, CR_SERVER_RPW_ENTRY, GpuSubmittedEntry)
64 {
65 Assert(CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry));
66
67 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, CR_SERVER_RPW_ENTRY_PBO_COMPLETED(pCurEntry));
68
69 void *pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
70
71 pCurEntry->pfnData(pCurEntry, pvData);
72
73 cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
74
75 cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, pCurEntry->Size.cx*pCurEntry->Size.cy*4, 0, GL_STREAM_READ_ARB);
76
77 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
78 }
79}
80
81static void crServerRpwWorkerGpuMarkGpuCompletedSubmitedLocked(PRTLISTNODE pGpuSubmitedList, PRTLISTNODE pWorkList)
82{
83 CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
84 RTListForEachSafe(pGpuSubmitedList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, GpuSubmittedEntry)
85 {
86 CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pCurEntry, Gpu);
87 RTListNodeRemove(&pCurEntry->GpuSubmittedEntry);
88 }
89
90 Assert(RTListIsEmpty(pGpuSubmitedList));
91
92 RTListForEachSafe(pWorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkerWorkEntry)
93 {
94 Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Worker));
95 RTListNodeRemove(&pCurEntry->WorkerWorkEntry);
96 if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry))
97 {
98 /* PBO mode, put to the GPU submitted queue*/
99 RTListAppend(pGpuSubmitedList, &pCurEntry->GpuSubmittedEntry);
100 CR_SERVER_RPW_ENTRY_TEX_PROMOTE(pCurEntry, Worker, Gpu);
101 }
102 else
103 {
104 /* no PBO, we are already done entry data processing, free it right away */
105 Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Gpu));
106 CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pCurEntry, Worker);
107 }
108 }
109}
110
111static void crServerRpwWorkerGetWorkLocked(CR_SERVER_RPW *pWorker, PRTLISTNODE pWorkList)
112{
113 CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
114 RTListForEachSafe(&pWorker->WorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkEntry)
115 {
116 RTListNodeRemove(&pCurEntry->WorkEntry);
117 RTListAppend(pWorkList, &pCurEntry->WorkerWorkEntry);
118 CR_SERVER_RPW_ENTRY_TEX_PROMOTE(pCurEntry, Submitted, Worker);
119 }
120}
121
122static DECLCALLBACK(int) crServerRpwWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
123{
124 RT_NOREF(ThreadSelf);
125
126 CR_SERVER_RPW *pWorker = (CR_SERVER_RPW *)pvUser;
127 RTMSINTERVAL cWaitMillis = RT_INDEFINITE_WAIT;
128 RTLISTNODE WorkList, GpuSubmittedList;
129 CR_SERVER_RPW_CTL_TYPE enmCtlType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
130 CR_SERVER_RPW_ENTRY *pCtlEntry = NULL;
131 CRMuralInfo *pDummyMural = crServerGetDummyMural(pWorker->ctxVisBits);
132 bool fExit = false;
133 bool fForceComplete = false;
134 bool fNotifyCmdCompleted = false;
135
136 CRASSERT(pDummyMural);
137
138 int rc = RTSemEventSignal(pWorker->Ctl.hCompleteEvent);
139 if (!RT_SUCCESS(rc))
140 {
141 crWarning("RTSemEventSignal failed rc %d", rc);
142 return rc;
143 }
144
145 RTListInit(&WorkList);
146 RTListInit(&GpuSubmittedList);
147
148 cr_server.head_spu->dispatch_table.MakeCurrent(pDummyMural->spuWindow, 0, pWorker->ctxId);
149
150 rc = RTCritSectEnter(&pWorker->CritSect);
151 if (!RT_SUCCESS(rc))
152 {
153 crWarning("RTCritSectEnter failed, rc %d", rc);
154 goto end;
155 }
156
157 for (;;)
158 {
159 /* the crit sect is locked here */
160
161 if (pWorker->Ctl.enmType != CR_SERVER_RPW_CTL_TYPE_UNDEFINED)
162 {
163 enmCtlType = pWorker->Ctl.enmType;
164 pCtlEntry = pWorker->Ctl.pEntry;
165 pWorker->Ctl.enmType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
166 pWorker->Ctl.pEntry = NULL;
167 }
168
169 crServerRpwWorkerGetWorkLocked(pWorker, &WorkList);
170
171 RTCritSectLeave(&pWorker->CritSect);
172
173 if (enmCtlType != CR_SERVER_RPW_CTL_TYPE_UNDEFINED)
174 {
175 switch (enmCtlType)
176 {
177 case CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE:
178 break;
179 case CR_SERVER_RPW_CTL_TYPE_TERM:
180 fExit = true;
181 break;
182 default:
183 crWarning("unexpected CtlType %d", enmCtlType);
184 break;
185 }
186 enmCtlType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
187 pCtlEntry = NULL;
188 fNotifyCmdCompleted = true;
189 }
190
191 bool fNewItems = !RTListIsEmpty(&WorkList);
192 bool fCompleted = false;
193
194 if (fNewItems)
195 {
196 crServerRpwWorkerGpuSubmit(&WorkList);
197 }
198
199 if (!RTListIsEmpty(&GpuSubmittedList))
200 {
201 if (fForceComplete || fNewItems)
202 {
203 crServerRpwWorkerGpuComplete(&GpuSubmittedList);
204 fForceComplete = false;
205 fCompleted = true;
206 }
207 }
208
209 rc = RTCritSectEnter(&pWorker->CritSect);
210 if (!RT_SUCCESS(rc))
211 {
212 crWarning("RTCritSectEnter failed, rc %d", rc);
213 break;
214 }
215
216 /* fNewGpuItems means new entries arrived. WorkList contains new GPU submitted data
217 * fCompleted means completion was performed, GpuSubmittedList contains old GPU submitted data,
218 * which is now completed and should be released */
219 if (fNewItems || fCompleted)
220 {
221 crServerRpwWorkerGpuMarkGpuCompletedSubmitedLocked(&GpuSubmittedList, &WorkList);
222 }
223
224 if (fExit || !fNewItems)
225 {
226 RTCritSectLeave(&pWorker->CritSect);
227
228 if (fNotifyCmdCompleted)
229 {
230 rc = RTSemEventSignal(pWorker->Ctl.hCompleteEvent);
231 if (!RT_SUCCESS(rc))
232 {
233 crWarning("RTSemEventSignal failed rc %d", rc);
234 break;
235 }
236 fNotifyCmdCompleted = false;
237 }
238
239 if (fExit)
240 break;
241
242 if (!RTListIsEmpty(&GpuSubmittedList))
243 cWaitMillis = 17; /* ~60Hz */
244 else
245 cWaitMillis = RT_INDEFINITE_WAIT;
246
247 rc = RTSemEventWait(pWorker->hSubmitEvent, cWaitMillis);
248 if (!RT_SUCCESS(rc) && rc != VERR_TIMEOUT)
249 {
250 crWarning("RTSemEventWait failed, rc %d", rc);
251 break;
252 }
253
254 if (rc == VERR_TIMEOUT)
255 {
256 Assert(!RTListIsEmpty(&GpuSubmittedList));
257 fForceComplete = true;
258 }
259
260 rc = RTCritSectEnter(&pWorker->CritSect);
261 if (!RT_SUCCESS(rc))
262 {
263 crWarning("RTCritSectEnter failed, rc %d", rc);
264 break;
265 }
266 }
267 }
268
269end:
270 cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0);
271
272 return rc;
273}
274
275static int crServerRpwCtlNotify(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
276{
277 RT_NOREF(pEntry);
278
279 int rc = RTSemEventSignal(pWorker->hSubmitEvent);
280 if (RT_SUCCESS(rc))
281 {
282 rc = RTSemEventWait(pWorker->Ctl.hCompleteEvent, RT_INDEFINITE_WAIT);
283 if (RT_SUCCESS(rc))
284 {
285 rc = pWorker->Ctl.rc;
286 if (!RT_SUCCESS(rc))
287 {
288 crWarning("WdCtl command failed rc %d", rc);
289 }
290 }
291 else
292 {
293 crWarning("RTSemEventWait failed rc %d", rc);
294 }
295 }
296 else
297 {
298 int tmpRc;
299 crWarning("RTSemEventSignal failed rc %d", rc);
300 tmpRc = RTCritSectEnter(&pWorker->CritSect);
301 if (RT_SUCCESS(tmpRc))
302 {
303 pWorker->Ctl.enmType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
304 pWorker->Ctl.pEntry = NULL;
305 RTCritSectLeave(&pWorker->CritSect);
306 }
307 else
308 {
309 crWarning("RTSemEventSignal failed tmpRc %d", tmpRc);
310 }
311 }
312
313 return rc;
314}
315
316static int crServerRpwCtl(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_CTL_TYPE enmType, CR_SERVER_RPW_ENTRY *pEntry)
317{
318 int rc = RTCritSectEnter(&pWorker->CritSect);
319 if (RT_SUCCESS(rc))
320 {
321 pWorker->Ctl.enmType = enmType;
322 pWorker->Ctl.pEntry = pEntry;
323 RTCritSectLeave(&pWorker->CritSect);
324 }
325 else
326 {
327 crWarning("RTCritSectEnter failed rc %d", rc);
328 return rc;
329 }
330
331 rc = crServerRpwCtlNotify(pWorker, pEntry);
332 if (!RT_SUCCESS(rc))
333 {
334 crWarning("crServerRpwCtlNotify failed rc %d", rc);
335 return rc;
336 }
337 return VINF_SUCCESS;
338}
339
340int crServerRpwInit(CR_SERVER_RPW *pWorker)
341{
342 int rc;
343
344 memset(pWorker, 0, sizeof (*pWorker));
345
346 RTListInit(&pWorker->WorkList);
347
348 rc = RTCritSectInit(&pWorker->CritSect);
349 if (RT_SUCCESS(rc))
350 {
351 rc = RTSemEventCreate(&pWorker->hSubmitEvent);
352 if (RT_SUCCESS(rc))
353 {
354 rc = RTSemEventCreate(&pWorker->Ctl.hCompleteEvent);
355 if (RT_SUCCESS(rc))
356 {
357 CRASSERT(cr_server.MainContextInfo.CreateInfo.realVisualBits);
358 CRASSERT(cr_server.MainContextInfo.SpuContext);
359
360 pWorker->ctxId = cr_server.head_spu->dispatch_table.CreateContext("", cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
361 if (pWorker->ctxId)
362 {
363 CRMuralInfo *pDummyMural;
364 pWorker->ctxVisBits = cr_server.MainContextInfo.CreateInfo.realVisualBits;
365 pDummyMural = crServerGetDummyMural(pWorker->ctxVisBits);
366 if (pDummyMural)
367 {
368 /* since CreateContext does not actually create it on some platforms, e.g. on win,
369 * we need to do MakeCurrent to ensure it is created.
370 * There is some black magic in doing that to work around ogl driver bugs
371 * (i.e. we need to switch offscreen rendering off before doing make current) */
372 CR_SERVER_CTX_SWITCH CtxSwitch;
373
374 crServerCtxSwitchPrepare(&CtxSwitch, NULL);
375
376 cr_server.head_spu->dispatch_table.Flush();
377
378 cr_server.head_spu->dispatch_table.MakeCurrent(pDummyMural->spuWindow, 0, pWorker->ctxId);
379
380 if (cr_server.currentCtxInfo)
381 {
382 CRASSERT(cr_server.currentMural);
383 cr_server.head_spu->dispatch_table.MakeCurrent(cr_server.currentMural->spuWindow, 0,
384 cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext);
385 }
386 else
387 cr_server.head_spu->dispatch_table.MakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
388
389 crServerCtxSwitchPostprocess(&CtxSwitch);
390
391 rc = RTThreadCreate(&pWorker->hThread, crServerRpwWorkerThread, pWorker, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CrServerDw");
392 if (RT_SUCCESS(rc))
393 {
394 rc = RTSemEventWait(pWorker->Ctl.hCompleteEvent, RT_INDEFINITE_WAIT);
395 if (RT_SUCCESS(rc))
396 {
397 return VINF_SUCCESS;
398 }
399 else
400 {
401 crWarning("RTSemEventWait failed rc %d", rc);
402 }
403 }
404 else
405 {
406 crWarning("RTThreadCreate failed rc %d", rc);
407 }
408 }
409 else
410 {
411 crWarning("Failed to get dummy mural");
412 rc = VERR_GENERAL_FAILURE;
413 }
414 cr_server.head_spu->dispatch_table.DestroyContext(pWorker->ctxId);
415 }
416 else
417 {
418 crWarning("CreateContext failed rc %d", rc);
419 }
420
421 RTSemEventDestroy(pWorker->Ctl.hCompleteEvent);
422 }
423 else
424 {
425 crWarning("RTSemEventCreate failed rc %d", rc);
426 }
427 RTSemEventDestroy(pWorker->hSubmitEvent);
428 }
429 else
430 {
431 crWarning("RTSemEventCreate failed rc %d", rc);
432 }
433
434 RTCritSectDelete(&pWorker->CritSect);
435 }
436 else
437 {
438 crWarning("RTCritSectInit failed rc %d", rc);
439 }
440
441 return rc;
442}
443
444int crServerRpwEntryResizeCleaned(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height)
445{
446 RT_NOREF(pWorker);
447
448 CRContext *pContext;
449 if (!width || !height)
450 {
451 return VINF_SUCCESS;
452 }
453
454 if (!cr_server.currentCtxInfo)
455 {
456 CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
457 if (!pDummy)
458 {
459 crWarning("crServerGetDummyMural failed");
460 return VERR_GENERAL_FAILURE;
461 }
462
463
464 crServerPerformMakeCurrent(pDummy, &cr_server.MainContextInfo);
465 }
466
467 Assert(width);
468 Assert(height);
469
470 pContext = cr_server.currentCtxInfo->pContext;
471
472 if (crStateIsBufferBound(&cr_server.StateTracker, GL_PIXEL_UNPACK_BUFFER_ARB))
473 {
474 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
475 }
476
477 for (int i = 0; i < 4; ++i)
478 {
479 cr_server.head_spu->dispatch_table.GenTextures(1, &pEntry->aidWorkerTexs[i]);
480
481 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, pEntry->aidWorkerTexs[i]);
482 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
483 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
484 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
485 cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
486 cr_server.head_spu->dispatch_table.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
487 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
488 }
489
490 pEntry->iTexDraw = -pEntry->iTexDraw;
491
492 if (crStateIsBufferBound(&cr_server.StateTracker, GL_PIXEL_UNPACK_BUFFER_ARB))
493 {
494 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pContext->bufferobject.unpackBuffer->hwid);
495 }
496
497 if (cr_server.bUsePBOForReadback)
498 {
499 for (int i = 0; i < 2; ++i)
500 {
501 cr_server.head_spu->dispatch_table.GenBuffersARB(1, &pEntry->aidPBOs[i]);
502 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pEntry->aidPBOs[i]);
503 cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, width*height*4, 0, GL_STREAM_READ_ARB);
504 }
505
506 if (crStateIsBufferBound(&cr_server.StateTracker, GL_PIXEL_PACK_BUFFER_ARB))
507 {
508 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pContext->bufferobject.packBuffer->hwid);
509 }
510 else
511 {
512 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
513 }
514 pEntry->iCurPBO = 0;
515 }
516
517
518 GLuint uid = pContext->texture.unit[pContext->texture.curTextureUnit].currentTexture2D->hwid;
519 cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
520
521
522 pEntry->Size.cx = width;
523 pEntry->Size.cy = height;
524
525 crServerRpwEntryDbgVerify(pEntry);
526
527 return VINF_SUCCESS;
528}
529
530int crServerRpwEntryCleanup(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
531{
532 if (!pEntry->Size.cx)
533 return VINF_SUCCESS;
534
535 int rc = crServerRpwEntryCancel(pWorker, pEntry);
536 if (!RT_SUCCESS(rc))
537 {
538 crWarning("crServerRpwEntryCancel failed rc %d", rc);
539 return rc;
540 }
541
542 if (!cr_server.currentCtxInfo)
543 {
544 CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
545 if (!pDummy)
546 {
547 crWarning("crServerGetDummyMural failed");
548 return VERR_GENERAL_FAILURE;
549 }
550
551
552 crServerPerformMakeCurrent(pDummy, &cr_server.MainContextInfo);
553 }
554
555 cr_server.head_spu->dispatch_table.DeleteTextures(4, pEntry->aidWorkerTexs);
556
557 if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pEntry))
558 {
559 cr_server.head_spu->dispatch_table.DeleteBuffersARB(2, pEntry->aidPBOs);
560 memset(pEntry->aidPBOs, 0, sizeof (pEntry->aidPBOs));
561 pEntry->iCurPBO = -1;
562 }
563
564 memset(pEntry->aidWorkerTexs, 0, sizeof (pEntry->aidWorkerTexs));
565 CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted);
566 CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Worker);
567 CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Gpu);
568 pEntry->iTexDraw = -1;
569 pEntry->iTexSubmitted = -2;
570 pEntry->iTexWorker = -3;
571 pEntry->iTexGpu = -4;
572 pEntry->Size.cx = 0;
573 pEntry->Size.cy = 0;
574 return VINF_SUCCESS;
575}
576
577int crServerRpwEntryResize(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height)
578{
579 if (!width || !height)
580 {
581 width = 0;
582 height = 0;
583 }
584
585 if (width == pEntry->Size.cx && width == pEntry->Size.cy)
586 return VINF_SUCCESS;
587
588 int rc = crServerRpwEntryCleanup(pWorker, pEntry);
589 if (!RT_SUCCESS(rc))
590 {
591 crWarning("crServerRpwEntryCleanup failed rc %d", rc);
592 return rc;
593 }
594
595 rc = crServerRpwEntryResizeCleaned(pWorker, pEntry, width, height);
596 if (!RT_SUCCESS(rc))
597 {
598 crWarning("crServerRpwEntryResizeCleaned failed rc %d", rc);
599 }
600 return rc;
601}
602
603int crServerRpwEntryInit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height, PFNCR_SERVER_RPW_DATA pfnData)
604{
605 memset(pEntry, 0, sizeof (*pEntry));
606
607 pEntry->iTexDraw = -1;
608 pEntry->iTexSubmitted = -2;
609 pEntry->iTexWorker = -3;
610 pEntry->iTexGpu = -4;
611 pEntry->iCurPBO = -1;
612 pEntry->pfnData = pfnData;
613 int rc = crServerRpwEntryResizeCleaned(pWorker, pEntry, width, height);
614 if (!RT_SUCCESS(rc))
615 {
616 crWarning("crServerRpwEntryResizeCleaned failed rc %d", rc);
617 return rc;
618 }
619 return VINF_SUCCESS;
620}
621
622int crServerRpwEntrySubmit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
623{
624 if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw))
625 {
626 crWarning("submitting empty entry, ignoting");
627 Assert(!pEntry->Size.cx);
628 Assert(!pEntry->Size.cy);
629 return VERR_INVALID_PARAMETER;
630 }
631
632 Assert(pEntry->Size.cx);
633 Assert(pEntry->Size.cy);
634
635 int rc = RTCritSectEnter(&pWorker->CritSect);
636 if (RT_SUCCESS(rc))
637 {
638 Assert(pWorker->Ctl.enmType == CR_SERVER_RPW_CTL_TYPE_UNDEFINED);
639 if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted))
640 {
641 CR_SERVER_RPW_ENTRY_TEX_PROMOTE_KEEPVALID(pEntry, Draw, Submitted);
642 RTListAppend(&pWorker->WorkList, &pEntry->WorkEntry);
643 }
644 else
645 {
646 CR_SERVER_RPW_ENTRY_TEX_XCHG_VALID(pEntry, Draw, Submitted);
647 }
648 RTCritSectLeave(&pWorker->CritSect);
649
650 RTSemEventSignal(pWorker->hSubmitEvent);
651 }
652 else
653 {
654 crWarning("RTCritSectEnter failed rc %d", rc);
655 return rc;
656 }
657
658 return rc;
659}
660
661static int crServerRpwEntryCancelCtl(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, CR_SERVER_RPW_CTL_TYPE enmType)
662{
663 if (CR_SERVER_RPW_CTL_TYPE_TERM == enmType && pEntry)
664 {
665 crWarning("Entry should be null for term request");
666 pEntry = NULL;
667 }
668
669 int rc = RTCritSectEnter(&pWorker->CritSect);
670 if (RT_SUCCESS(rc))
671 {
672 if (pEntry)
673 {
674 if (CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted))
675 {
676 CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pEntry, Submitted);
677 RTListNodeRemove(&pEntry->WorkEntry);
678 }
679
680 if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Worker) && !CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Gpu))
681 {
682 /* can cancel it wight away */
683 RTCritSectLeave(&pWorker->CritSect);
684 return VINF_SUCCESS;
685 }
686 }
687 else
688 {
689 CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
690 RTListForEachSafe(&pWorker->WorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkEntry)
691 {
692 CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Submitted);
693 CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pEntry, Submitted);
694 RTListNodeRemove(&pCurEntry->WorkEntry);
695 }
696 }
697 pWorker->Ctl.enmType = enmType;
698 pWorker->Ctl.pEntry = pEntry;
699 RTCritSectLeave(&pWorker->CritSect);
700 }
701 else
702 {
703 crWarning("RTCritSectEnter failed rc %d", rc);
704 return rc;
705 }
706
707 rc = crServerRpwCtlNotify(pWorker, pEntry);
708 if (!RT_SUCCESS(rc))
709 {
710 crWarning("crServerRpwCtlNotify failed rc %d", rc);
711 }
712 return VINF_SUCCESS;
713}
714
715int crServerRpwEntryWaitComplete(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
716{
717 int rc = crServerRpwCtl(pWorker, CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE, pEntry);
718 if (!RT_SUCCESS(rc))
719 {
720 crWarning("crServerRpwCtl failed rc %d", rc);
721 }
722 return rc;
723}
724
725int crServerRpwEntryCancel(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
726{
727 return crServerRpwEntryCancelCtl(pWorker, pEntry, CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE);
728}
729
730static int crServerRpwCtlTerm(CR_SERVER_RPW *pWorker)
731{
732 int rc = crServerRpwEntryCancelCtl(pWorker, NULL, CR_SERVER_RPW_CTL_TYPE_TERM);
733 if (!RT_SUCCESS(rc))
734 {
735 crWarning("crServerRpwCtl failed rc %d", rc);
736 }
737 return rc;
738}
739
740int crServerRpwTerm(CR_SERVER_RPW *pWorker)
741{
742 int rc = crServerRpwCtlTerm(pWorker);
743 if (!RT_SUCCESS(rc))
744 {
745 crWarning("crServerRpwCtlTerm failed rc %d", rc);
746 return rc;
747 }
748
749 rc = RTThreadWait(pWorker->hThread, RT_INDEFINITE_WAIT, NULL);
750 if (!RT_SUCCESS(rc))
751 {
752 crWarning("RTThreadWait failed rc %d", rc);
753 return rc;
754 }
755
756 RTSemEventDestroy(pWorker->Ctl.hCompleteEvent);
757 RTSemEventDestroy(pWorker->hSubmitEvent);
758 RTCritSectDelete(&pWorker->CritSect);
759
760 return VINF_SUCCESS;
761}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette