VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/blitter.cpp@ 46085

Last change on this file since 46085 was 46085, checked in by vboxsync, 12 years ago

crOpenGL: some blitter fixes

  • Property svn:executable set to *
File size: 22.3 KB
Line 
1/* $Id$ */
2
3/** @file
4 * Blitter API implementation
5 */
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#include "cr_blitter.h"
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "cr_mem.h"
24#include "cr_string.h"
25
26#include <iprt/cdefs.h>
27#include <iprt/types.h>
28#include <iprt/mem.h>
29
30
31/* @param pCtxBase - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
32 * @param fCreateNewCtx - if true - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
33 * its id field is used to specified the shared context id to be used for blitter context.
34 * The id can be null to specify no shared context is needed
35 * if false - if pCtxBase is NOT null AND its id field is NOT null -
36 * specified the blitter context to be used
37 * blitter treats it as if it has default ogl state.
38 * otherwise -
39 * the blitter works in a "no-context" mode, i.e. a caller is responsible
40 * to making a proper context current before calling the blitter.
41 * Note that BltEnter/Leave MUST still be called, but the proper context
42 * must be set before doing BltEnter, and ResoreContext info is ignored in that case.
43 * Also note that blitter caches the current window info, and assumes the current context's values are preserved
44 * wrt that window before the calls, so if one uses different contexts for one blitter,
45 * the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrent(pBlitter, NULL)
46 * @param fForceDrawBlt - if true - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
47 * This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
48 */
49int CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, SPUDispatchTable *pDispatch)
50{
51 if (pCtxBase && pCtxBase->Base.id < 0)
52 {
53 crWarning("Default share context not initialized!");
54 return VERR_INVALID_PARAMETER;
55 }
56
57 if (!pCtxBase && fCreateNewCtx)
58 {
59 crWarning("pCtxBase is zero while fCreateNewCtx is set!");
60 return VERR_INVALID_PARAMETER;
61 }
62
63 memset(pBlitter, 0, sizeof (*pBlitter));
64
65 pBlitter->pDispatch = pDispatch;
66 if (pCtxBase)
67 pBlitter->CtxInfo = *pCtxBase;
68
69 pBlitter->Flags.ForceDrawBlit = fForceDrawBlt;
70
71 if (fCreateNewCtx)
72 {
73 pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
74 if (!pBlitter->CtxInfo.Base.id)
75 {
76 memset(pBlitter, 0, sizeof (*pBlitter));
77 crWarning("CreateContext failed!");
78 return VERR_GENERAL_FAILURE;
79 }
80 pBlitter->Flags.CtxCreated = 1;
81 }
82
83 return VINF_SUCCESS;
84}
85
86void CrBltTerm(PCR_BLITTER pBlitter)
87{
88 if (pBlitter->Flags.CtxCreated)
89 pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
90}
91
92int CrBltMuralSetCurrent(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
93{
94 if (pMural)
95 {
96 if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
97 return VINF_SUCCESS;
98 memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
99 }
100 else
101 {
102 if (CrBltIsEntered(pBlitter))
103 {
104 crWarning("can not set null mural for entered bleater");
105 return VERR_INVALID_STATE;
106 }
107 if (!pBlitter->CurrentMural.Base.id)
108 return VINF_SUCCESS;
109 pBlitter->CurrentMural.Base.id = 0;
110 }
111
112 pBlitter->Flags.CurrentMuralChanged = 1;
113
114 if (!CrBltIsEntered(pBlitter))
115 return VINF_SUCCESS;
116 else if (!pBlitter->CtxInfo.Base.id)
117 {
118 crWarning("setting current mural for entered no-context blitter");
119 return VERR_INVALID_STATE;
120 }
121
122 pBlitter->pDispatch->Flush();
123
124 pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
125
126 return VINF_SUCCESS;
127}
128
129static DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
130{
131 GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
132 pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
133 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
134 pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
135
136 for (uint32_t i = 0; i < cRects; ++i)
137 {
138 const RTRECT * pSrcRect = &paSrcRect[i];
139 const RTRECT * pDstRect = &paDstRect[i];
140 int32_t srcY1;
141 int32_t srcY2;
142 int32_t dstY1;
143 int32_t dstY2;
144 int32_t srcX1 = pSrcRect->xLeft;
145 int32_t srcX2 = pSrcRect->xRight;
146 int32_t dstX1 = pDstRect->xLeft;
147 int32_t dstX2 = pDstRect->xRight;
148
149 if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
150 {
151 srcY1 = pSrc->height - pSrcRect->yTop;
152 srcY2 = pSrc->height - pSrcRect->yBottom;
153 }
154 else
155 {
156 srcY1 = pSrcRect->yTop;
157 srcY2 = pSrcRect->yBottom;
158 }
159
160 if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
161 {
162 dstY1 = pDstSize->cy - pDstRect->yTop;
163 dstY2 = pDstSize->cy - pDstRect->yBottom;
164 }
165 else
166 {
167 dstY1 = pDstRect->yTop;
168 dstY2 = pDstRect->yBottom;
169 }
170
171 if (srcY1 > srcY2)
172 {
173 if (dstY1 > dstY2)
174 {
175 /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
176 int32_t tmp = srcY1;
177 srcY1 = srcY2;
178 srcY2 = tmp;
179 tmp = dstY1;
180 dstY1 = dstY2;
181 dstY2 = tmp;
182 }
183 }
184
185 if (srcX1 > srcX2)
186 {
187 if (dstX1 > dstX2)
188 {
189 /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
190 int32_t tmp = srcX1;
191 srcX1 = srcX2;
192 srcX2 = tmp;
193 tmp = dstX1;
194 dstX1 = dstX2;
195 dstX2 = tmp;
196 }
197 }
198
199 pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
200 dstX1, dstY1, dstX2, dstY2,
201 GL_COLOR_BUFFER_BIT, filter);
202 }
203
204 return VINF_SUCCESS;
205}
206
207/* GL_TRIANGLE_FAN */
208DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
209{
210 /* going ccw:
211 * 1. (left;top) 4. (right;top)
212 * | ^
213 * > |
214 * 2. (left;bottom) -> 3. (right;bottom) */
215 /* xLeft yTop */
216 pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
217 pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
218
219 /* xLeft yBottom */
220 pBuff[2] = pBuff[0];
221 pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
222
223 /* xRight yBottom */
224 pBuff[4] = ((float)pRect->xRight)/((float)normalX);
225 pBuff[5] = pBuff[3];
226
227 /* xRight yTop */
228 pBuff[6] = pBuff[4];
229 pBuff[7] = pBuff[1];
230 return &pBuff[8];
231}
232
233DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
234{
235 /* xLeft yTop */
236 pBuff[0] = pRect->xLeft;
237 pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
238
239 /* xLeft yBottom */
240 pBuff[2] = pBuff[0];
241 pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
242
243 /* xRight yBottom */
244 pBuff[4] = pRect->xRight;
245 pBuff[5] = pBuff[3];
246
247 /* xRight yTop */
248 pBuff[6] = pBuff[4];
249 pBuff[7] = pBuff[1];
250 return &pBuff[8];
251}
252
253DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
254{
255 GLubyte iBase = *piBase;
256 /* triangle 1 */
257 pIndex[0] = iBase;
258 pIndex[1] = iBase + 1;
259 pIndex[2] = iBase + 2;
260
261 /* triangle 2 */
262 pIndex[3] = iBase;
263 pIndex[4] = iBase + 2;
264 pIndex[5] = iBase + 3;
265 *piBase = iBase + 4;
266 return pIndex + 6;
267}
268
269/* Indexed GL_TRIANGLES */
270DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
271{
272 GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
273 return ret;
274}
275
276DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
277{
278 GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
279
280 if (ppIndex)
281 *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
282
283 return ret;
284}
285
286DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
287{
288 return cRects * 4;
289}
290
291#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
292
293DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
294{
295 return 6 * cRects;
296}
297
298
299static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
300{
301 uint32_t i;
302 for (i = 0; i < cRects; ++i)
303 {
304 pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
305 }
306
307
308 if (ppIndex)
309 {
310 GLubyte *pIndex = (GLubyte*)pBuff;
311 *ppIndex = pIndex;
312 for (i = 0; i < cRects; ++i)
313 {
314 pIndex = crBltVtFillRectIndicies(pIndex, piBase);
315 }
316 pBuff = (GLfloat*)pIndex;
317 }
318
319 return pBuff;
320}
321
322static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
323{
324 if (pBuffer->cbBuffer < cbBuffer)
325 {
326 if (pBuffer->pvBuffer)
327 {
328 RTMemFree(pBuffer->pvBuffer);
329 }
330
331#ifndef DEBUG_misha
332 /* debugging: ensure we calculate proper buffer size */
333 cbBuffer += 16;
334#endif
335
336 pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
337 if (pBuffer->pvBuffer)
338 pBuffer->cbBuffer = cbBuffer;
339 else
340 {
341 crWarning("failed to allocate buffer of size %d", cbBuffer);
342 pBuffer->cbBuffer = 0;
343 }
344 }
345 return pBuffer->pvBuffer;
346}
347
348static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
349{
350 bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
351 if (pBlitter->CurrentSetSize.cx != pDstSize->cx
352 || pBlitter->CurrentSetSize.cy != pDstSize->cy)
353 {
354 pBlitter->CurrentSetSize = *pDstSize;
355 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
356 pBlitter->pDispatch->LoadIdentity();
357 pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
358 fUpdateViewport = true;
359 }
360
361 if (fUpdateViewport)
362 {
363 pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
364 pBlitter->Flags.CurrentMuralChanged = 0;
365 }
366
367 pBlitter->Flags.LastWasFBODraw = fFBODraw;
368}
369
370static DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
371{
372 GLuint normalX, normalY;
373 uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
374 uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
375 Assert(srcHeight == dstHeight);
376
377 switch (pSrc->target)
378 {
379 case GL_TEXTURE_2D:
380 {
381 normalX = pSrc->width;
382 normalY = pSrc->height;
383 break;
384 }
385
386 case GL_TEXTURE_RECTANGLE_ARB:
387 {
388 normalX = 1;
389 normalY = 1;
390 break;
391 }
392
393 default:
394 {
395 crWarning("Unsupported texture target 0x%x", pSrc->target);
396 return VERR_INVALID_PARAMETER;
397 }
398 }
399
400 Assert(pSrc->hwid);
401
402 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
403
404 if (cRects == 1)
405 {
406 /* just optimizatino to draw a single rect with GL_TRIANGLE_FAN */
407 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
408 GLfloat *pVerticies;
409 GLfloat *pTexCoords;
410 GLuint cElements = crBltVtGetNumVerticiesTF(1);
411 if (bUseSameVerticies)
412 {
413 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies));
414 crBltVtRectTFNormalized(paDstRect, normalX, normalY, pVerticies, dstHeight);
415 pTexCoords = pVerticies;
416 }
417 else
418 {
419 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
420 pTexCoords = crBltVtRectTFNormalized(paDstRect, 1, 1, pVerticies, dstHeight);
421 crBltVtRectTFNormalized(paSrcRect, normalX, normalY, pTexCoords, srcHeight);
422 }
423
424 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
425 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
426
427 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
428 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
429
430 pBlitter->pDispatch->Enable(pSrc->target);
431
432 pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
433
434 pBlitter->pDispatch->Disable(pSrc->target);
435
436 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
437 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
438 }
439 else
440 {
441 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
442 GLfloat *pVerticies;
443 GLfloat *pTexCoords;
444 GLubyte *pIndicies;
445 GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
446 GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
447 GLubyte iIdxBase = 0;
448 if (bUseSameVerticies)
449 {
450 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
451 crBltVtRectsITNormalized(paDstRect, cRects, normalX, normalY, pVerticies, &pIndicies, &iIdxBase, dstHeight);
452 pTexCoords = pVerticies;
453 }
454 else
455 {
456 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
457 pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
458 crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
459 }
460
461 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
462 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
463
464 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
465 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
466
467 pBlitter->pDispatch->Enable(pSrc->target);
468
469 pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
470
471 pBlitter->pDispatch->Disable(pSrc->target);
472
473 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
474 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
475 }
476
477 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
478
479 return VINF_SUCCESS;
480}
481
482static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
483{
484 const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
485 if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
486 {
487 pBlitter->Flags.SupportsFBO = 1;
488 pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
489 Assert(pBlitter->idFBO);
490 }
491 else
492 crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
493
494 /* BlitFramebuffer seems to be buggy on Intel,
495 * try always glDrawXxx for now */
496 if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
497 {
498 pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
499 }
500 else
501 {
502// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
503 pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
504 }
505
506 /* defaults. but just in case */
507 pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
508 pBlitter->pDispatch->LoadIdentity();
509 pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
510 pBlitter->pDispatch->LoadIdentity();
511
512 return VINF_SUCCESS;
513}
514
515void CrBltLeave(PCR_BLITTER pBlitter)
516{
517 Assert(CrBltIsEntered(pBlitter));
518
519 if (pBlitter->Flags.SupportsFBO)
520 {
521 pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
522 pBlitter->pDispatch->DrawBuffer(GL_BACK);
523 pBlitter->pDispatch->ReadBuffer(GL_BACK);
524 }
525
526 pBlitter->pDispatch->Flush();
527
528 if (pBlitter->CtxInfo.Base.id)
529 {
530 if (pBlitter->pRestoreCtxInfo != &pBlitter->CtxInfo)
531 {
532 pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0, pBlitter->pRestoreCtxInfo->Base.id);
533 }
534 else
535 {
536 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
537 }
538 }
539
540 pBlitter->pRestoreCtxInfo = NULL;
541}
542
543int CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
544{
545 if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
546 {
547 crWarning("current mural not initialized!");
548 return VERR_INVALID_STATE;
549 }
550
551 if (CrBltIsEntered(pBlitter))
552 {
553 crWarning("blitter is entered already!");
554 return VERR_INVALID_STATE;
555 }
556
557 if (pBlitter->CurrentMural.Base.id) /* <- pBlitter->CurrentMural.Base.id can be null if the blitter is in a "no-context" mode (see comments to BltInit for detail)*/
558 {
559 if (pRestoreCtxInfo)
560 pBlitter->pDispatch->Flush();
561 pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
562 }
563 else
564 {
565 if (pRestoreCtxInfo)
566 {
567 crWarning("pRestoreCtxInfo is not NULL for \"no-context\" blitter");
568 pRestoreCtxInfo = NULL;
569 }
570 }
571
572 if (pRestoreCtxInfo)
573 {
574 pBlitter->pRestoreCtxInfo = pRestoreCtxInfo;
575 pBlitter->pRestoreMural = pRestoreMural;
576 }
577 else
578 {
579 pBlitter->pRestoreCtxInfo = &pBlitter->CtxInfo;
580 }
581
582 if (pBlitter->Flags.Initialized)
583 return VINF_SUCCESS;
584
585 int rc = crBltInitOnMakeCurent(pBlitter);
586 if (RT_SUCCESS(rc))
587 {
588 pBlitter->Flags.Initialized = 1;
589 return VINF_SUCCESS;
590 }
591
592 crWarning("crBltInitOnMakeCurent failed, rc %d", rc);
593 CrBltLeave(pBlitter);
594 return rc;
595}
596
597static void crBltBlitTexBuf(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const RTRECTSIZE *pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
598{
599 pBlitter->pDispatch->DrawBuffer(enmDstBuff);
600
601 crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
602
603 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
604}
605
606void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
607{
608 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
609 crBltCheckSetupViewport(pBlitter, &DstSize, false);
610}
611
612void CrBltBlitTexMural(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
613{
614 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
615
616 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
617
618 crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, GL_BACK, &DstSize, paDstRects, cRects, fFlags);
619}
620
621void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
622{
623 RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
624
625 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
626
627 /* TODO: mag/min filters ? */
628
629 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
630
631// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
632// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
633
634 crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
635
636 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
637}
638
639void CrBltPresent(PCR_BLITTER pBlitter)
640{
641 if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
642 pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
643 else
644 pBlitter->pDispatch->Flush();
645}
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