VirtualBox

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

Last change on this file since 54934 was 50277, checked in by vboxsync, 11 years ago

crOpenGL: correct way of dealing with CreateInfo

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