VirtualBox

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

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

crOpenGL: TexPresent fixes

  • Property svn:executable set to *
File size: 25.0 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 memset(pBlitter, 0, sizeof (*pBlitter));
91}
92
93int CrBltMuralSetCurrent(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
94{
95 if (pMural)
96 {
97 if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
98 return VINF_SUCCESS;
99 memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
100 }
101 else
102 {
103 if (CrBltIsEntered(pBlitter))
104 {
105 crWarning("can not set null mural for entered bleater");
106 return VERR_INVALID_STATE;
107 }
108 if (!pBlitter->CurrentMural.Base.id)
109 return VINF_SUCCESS;
110 pBlitter->CurrentMural.Base.id = 0;
111 }
112
113 pBlitter->Flags.CurrentMuralChanged = 1;
114
115 if (!CrBltIsEntered(pBlitter))
116 return VINF_SUCCESS;
117 else if (!pBlitter->CtxInfo.Base.id)
118 {
119 crWarning("setting current mural for entered no-context blitter");
120 return VERR_INVALID_STATE;
121 }
122
123 pBlitter->pDispatch->Flush();
124
125 pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
126
127 return VINF_SUCCESS;
128}
129
130static 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)
131{
132 GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
133 pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
134 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
135 pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
136
137 for (uint32_t i = 0; i < cRects; ++i)
138 {
139 const RTRECT * pSrcRect = &paSrcRect[i];
140 const RTRECT * pDstRect = &paDstRect[i];
141 int32_t srcY1;
142 int32_t srcY2;
143 int32_t dstY1;
144 int32_t dstY2;
145 int32_t srcX1 = pSrcRect->xLeft;
146 int32_t srcX2 = pSrcRect->xRight;
147 int32_t dstX1 = pDstRect->xLeft;
148 int32_t dstX2 = pDstRect->xRight;
149
150 if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
151 {
152 srcY1 = pSrc->height - pSrcRect->yTop;
153 srcY2 = pSrc->height - pSrcRect->yBottom;
154 }
155 else
156 {
157 srcY1 = pSrcRect->yTop;
158 srcY2 = pSrcRect->yBottom;
159 }
160
161 if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
162 {
163 dstY1 = pDstSize->cy - pDstRect->yTop;
164 dstY2 = pDstSize->cy - pDstRect->yBottom;
165 }
166 else
167 {
168 dstY1 = pDstRect->yTop;
169 dstY2 = pDstRect->yBottom;
170 }
171
172 if (srcY1 > srcY2)
173 {
174 if (dstY1 > dstY2)
175 {
176 /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
177 int32_t tmp = srcY1;
178 srcY1 = srcY2;
179 srcY2 = tmp;
180 tmp = dstY1;
181 dstY1 = dstY2;
182 dstY2 = tmp;
183 }
184 }
185
186 if (srcX1 > srcX2)
187 {
188 if (dstX1 > dstX2)
189 {
190 /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
191 int32_t tmp = srcX1;
192 srcX1 = srcX2;
193 srcX2 = tmp;
194 tmp = dstX1;
195 dstX1 = dstX2;
196 dstX2 = tmp;
197 }
198 }
199
200 pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
201 dstX1, dstY1, dstX2, dstY2,
202 GL_COLOR_BUFFER_BIT, filter);
203 }
204
205 return VINF_SUCCESS;
206}
207
208/* GL_TRIANGLE_FAN */
209DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
210{
211 /* going ccw:
212 * 1. (left;top) 4. (right;top)
213 * | ^
214 * > |
215 * 2. (left;bottom) -> 3. (right;bottom) */
216 /* xLeft yTop */
217 pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
218 pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
219
220 /* xLeft yBottom */
221 pBuff[2] = pBuff[0];
222 pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
223
224 /* xRight yBottom */
225 pBuff[4] = ((float)pRect->xRight)/((float)normalX);
226 pBuff[5] = pBuff[3];
227
228 /* xRight yTop */
229 pBuff[6] = pBuff[4];
230 pBuff[7] = pBuff[1];
231 return &pBuff[8];
232}
233
234DECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
235{
236 for (uint32_t i = 0; i < cRects; ++i)
237 {
238 pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
239 }
240 return pBuff;
241}
242
243DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
244{
245 /* xLeft yTop */
246 pBuff[0] = pRect->xLeft;
247 pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
248
249 /* xLeft yBottom */
250 pBuff[2] = pBuff[0];
251 pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
252
253 /* xRight yBottom */
254 pBuff[4] = pRect->xRight;
255 pBuff[5] = pBuff[3];
256
257 /* xRight yTop */
258 pBuff[6] = pBuff[4];
259 pBuff[7] = pBuff[1];
260 return &pBuff[8];
261}
262
263DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
264{
265 GLubyte iBase = *piBase;
266 /* triangle 1 */
267 pIndex[0] = iBase;
268 pIndex[1] = iBase + 1;
269 pIndex[2] = iBase + 2;
270
271 /* triangle 2 */
272 pIndex[3] = iBase;
273 pIndex[4] = iBase + 2;
274 pIndex[5] = iBase + 3;
275 *piBase = iBase + 4;
276 return pIndex + 6;
277}
278
279/* Indexed GL_TRIANGLES */
280DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
281{
282 GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
283 return ret;
284}
285
286DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
287{
288 GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
289
290 if (ppIndex)
291 *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
292
293 return ret;
294}
295
296DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
297{
298 return cRects * 4;
299}
300
301#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
302
303DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
304{
305 return 6 * cRects;
306}
307
308
309static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
310{
311 uint32_t i;
312 for (i = 0; i < cRects; ++i)
313 {
314 pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
315 }
316
317
318 if (ppIndex)
319 {
320 GLubyte *pIndex = (GLubyte*)pBuff;
321 *ppIndex = pIndex;
322 for (i = 0; i < cRects; ++i)
323 {
324 pIndex = crBltVtFillRectIndicies(pIndex, piBase);
325 }
326 pBuff = (GLfloat*)pIndex;
327 }
328
329 return pBuff;
330}
331
332static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
333{
334 if (pBuffer->cbBuffer < cbBuffer)
335 {
336 if (pBuffer->pvBuffer)
337 {
338 RTMemFree(pBuffer->pvBuffer);
339 }
340
341#ifndef DEBUG_misha
342 /* debugging: ensure we calculate proper buffer size */
343 cbBuffer += 16;
344#endif
345
346 pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
347 if (pBuffer->pvBuffer)
348 pBuffer->cbBuffer = cbBuffer;
349 else
350 {
351 crWarning("failed to allocate buffer of size %d", cbBuffer);
352 pBuffer->cbBuffer = 0;
353 }
354 }
355 return pBuffer->pvBuffer;
356}
357
358static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
359{
360 bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
361 if (pBlitter->CurrentSetSize.cx != pDstSize->cx
362 || pBlitter->CurrentSetSize.cy != pDstSize->cy)
363 {
364 pBlitter->CurrentSetSize = *pDstSize;
365 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
366 pBlitter->pDispatch->LoadIdentity();
367 pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
368 fUpdateViewport = true;
369 }
370
371 if (fUpdateViewport)
372 {
373 pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
374 pBlitter->Flags.CurrentMuralChanged = 0;
375 }
376
377 pBlitter->Flags.LastWasFBODraw = fFBODraw;
378}
379
380static 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)
381{
382 GLuint normalX, normalY;
383 uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
384 uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
385
386 switch (pSrc->target)
387 {
388 case GL_TEXTURE_2D:
389 {
390 normalX = pSrc->width;
391 normalY = pSrc->height;
392 break;
393 }
394
395 case GL_TEXTURE_RECTANGLE_ARB:
396 {
397 normalX = 1;
398 normalY = 1;
399 break;
400 }
401
402 default:
403 {
404 crWarning("Unsupported texture target 0x%x", pSrc->target);
405 return VERR_INVALID_PARAMETER;
406 }
407 }
408
409 Assert(pSrc->hwid);
410
411 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
412
413 if (cRects == 1)
414 {
415 /* just optimization to draw a single rect with GL_TRIANGLE_FAN */
416 GLfloat *pVerticies;
417 GLfloat *pTexCoords;
418 GLuint cElements = crBltVtGetNumVerticiesTF(cRects);
419
420 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
421 pTexCoords = crBltVtRectsTFNormalized(paDstRect, cRects, 1, 1, pVerticies, dstHeight);
422 crBltVtRectsTFNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, srcHeight);
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 GLfloat *pVerticies;
442 GLfloat *pTexCoords;
443 GLubyte *pIndicies;
444 GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
445 GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
446 GLubyte iIdxBase = 0;
447
448 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
449 pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
450 crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
451
452 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
453 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
454
455 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
456 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
457
458 pBlitter->pDispatch->Enable(pSrc->target);
459
460 pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
461
462 pBlitter->pDispatch->Disable(pSrc->target);
463
464 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
465 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
466 }
467
468 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
469
470 return VINF_SUCCESS;
471}
472
473static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
474{
475 const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
476 if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
477 {
478 pBlitter->Flags.SupportsFBO = 1;
479 pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
480 Assert(pBlitter->idFBO);
481 }
482 else
483 crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
484
485 /* BlitFramebuffer seems to be buggy on Intel,
486 * try always glDrawXxx for now */
487 if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
488 {
489 pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
490 }
491 else
492 {
493// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
494 pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
495 }
496
497 /* defaults. but just in case */
498 pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
499 pBlitter->pDispatch->LoadIdentity();
500 pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
501 pBlitter->pDispatch->LoadIdentity();
502
503 return VINF_SUCCESS;
504}
505
506void CrBltLeave(PCR_BLITTER pBlitter)
507{
508 if (!CrBltIsEntered(pBlitter))
509 {
510 crWarning("CrBltLeave: blitter not entered");
511 return;
512 }
513
514 if (pBlitter->Flags.SupportsFBO)
515 {
516 pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
517 pBlitter->pDispatch->DrawBuffer(GL_BACK);
518 pBlitter->pDispatch->ReadBuffer(GL_BACK);
519 }
520
521 pBlitter->pDispatch->Flush();
522
523 if (pBlitter->CtxInfo.Base.id)
524 {
525 if (pBlitter->pRestoreCtxInfo != &pBlitter->CtxInfo)
526 {
527 pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0, pBlitter->pRestoreCtxInfo->Base.id);
528 }
529 else
530 {
531 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
532 }
533 }
534
535 pBlitter->pRestoreCtxInfo = NULL;
536}
537
538int CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
539{
540 if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
541 {
542 crWarning("current mural not initialized!");
543 return VERR_INVALID_STATE;
544 }
545
546 if (CrBltIsEntered(pBlitter))
547 {
548 crWarning("blitter is entered already!");
549 return VERR_INVALID_STATE;
550 }
551
552 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)*/
553 {
554 if (pRestoreCtxInfo)
555 pBlitter->pDispatch->Flush();
556 pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
557 }
558 else
559 {
560 if (pRestoreCtxInfo)
561 {
562 crWarning("pRestoreCtxInfo is not NULL for \"no-context\" blitter");
563 pRestoreCtxInfo = NULL;
564 }
565 }
566
567 if (pRestoreCtxInfo)
568 {
569 pBlitter->pRestoreCtxInfo = pRestoreCtxInfo;
570 pBlitter->pRestoreMural = pRestoreMural;
571 }
572 else
573 {
574 pBlitter->pRestoreCtxInfo = &pBlitter->CtxInfo;
575 }
576
577 if (pBlitter->Flags.Initialized)
578 return VINF_SUCCESS;
579
580 int rc = crBltInitOnMakeCurent(pBlitter);
581 if (RT_SUCCESS(rc))
582 {
583 pBlitter->Flags.Initialized = 1;
584 return VINF_SUCCESS;
585 }
586
587 crWarning("crBltInitOnMakeCurent failed, rc %d", rc);
588 CrBltLeave(pBlitter);
589 return rc;
590}
591
592static 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)
593{
594 pBlitter->pDispatch->DrawBuffer(enmDstBuff);
595
596 crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
597
598 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
599}
600
601void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
602{
603 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
604 crBltCheckSetupViewport(pBlitter, &DstSize, false);
605}
606
607void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
608{
609 if (!CrBltIsEntered(pBlitter))
610 {
611 crWarning("CrBltBlitTexMural: blitter not entered");
612 return;
613 }
614
615 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
616
617 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
618
619 crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
620}
621
622void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
623{
624 if (!CrBltIsEntered(pBlitter))
625 {
626 crWarning("CrBltBlitTexTex: blitter not entered");
627 return;
628 }
629
630 RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
631
632 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
633
634 /* TODO: mag/min filters ? */
635
636 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
637
638// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
639// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
640
641 crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
642
643 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
644}
645
646void CrBltPresent(PCR_BLITTER pBlitter)
647{
648 if (!CrBltIsEntered(pBlitter))
649 {
650 crWarning("CrBltPresent: blitter not entered");
651 return;
652 }
653
654 if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
655 pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
656 else
657 pBlitter->pDispatch->Flush();
658}
659
660static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
661{
662 memset(pDst, 0, sizeof (*pDst));
663 if (enmFormat != GL_RGBA
664 && enmFormat != GL_BGRA)
665 {
666 crWarning("unsupported format 0x%x", enmFormat);
667 return VERR_NOT_IMPLEMENTED;
668 }
669
670 uint32_t bpp = 32;
671
672 uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
673 uint32_t cbData = pitch * pSrc->height;
674 pDst->pvData = RTMemAllocZ(cbData);
675 if (!pDst->pvData)
676 {
677 crWarning("RTMemAlloc failed");
678 return VERR_NO_MEMORY;
679 }
680
681#ifdef DEBUG_misha
682 {
683 char *pTmp = (char*)pDst->pvData;
684 for (uint32_t i = 0; i < cbData; ++i)
685 {
686 pTmp[i] = (char)((1 << i) % 255);
687 }
688 }
689#endif
690
691 pDst->cbData = cbData;
692 pDst->enmFormat = enmFormat;
693 pDst->width = pSrc->width;
694 pDst->height = pSrc->height;
695 pDst->bpp = bpp;
696 pDst->pitch = pitch;
697 return VINF_SUCCESS;
698}
699
700VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
701{
702 if (!CrBltIsEntered(pBlitter))
703 {
704 crWarning("CrBltImgGetTex: blitter not entered");
705 return VERR_INVALID_STATE;
706 }
707
708 int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
709 if (!RT_SUCCESS(rc))
710 {
711 crWarning("crBltImgCreateForTex failed, rc %d", rc);
712 return rc;
713 }
714 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
715
716#ifdef DEBUG_misha
717 {
718 GLint width = 0, height = 0, depth = 0;
719 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
720 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
721 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
722
723 Assert(width == pSrc->width);
724 Assert(height == pSrc->height);
725// Assert(depth == pSrc->depth);
726 }
727#endif
728
729 pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
730
731 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
732 return VINF_SUCCESS;
733}
734
735VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
736{
737 if (!CrBltIsEntered(pBlitter))
738 {
739 crWarning("CrBltImgGetMural: blitter not entered");
740 return VERR_INVALID_STATE;
741 }
742
743 crWarning("NOT IMPLEMENTED");
744 return VERR_NOT_IMPLEMENTED;
745}
746
747VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
748{
749 if (!CrBltIsEntered(pBlitter))
750 {
751 crWarning("CrBltImgFree: blitter not entered");
752 return;
753 }
754
755 if (pDst->pvData)
756 {
757 RTMemFree(pDst->pvData);
758 pDst->pvData = NULL;
759 }
760}
761
Note: See TracBrowser for help on using the repository browser.

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