VirtualBox

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

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

crOpenGL: fixed bug found by gcc

  • Property svn:executable set to *
File size: 25.7 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(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
235{
236 /* xLeft yTop */
237 pBuff[0] = pRect->xLeft;
238 pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
239
240 /* xLeft yBottom */
241 pBuff[2] = pBuff[0];
242 pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
243
244 /* xRight yBottom */
245 pBuff[4] = pRect->xRight;
246 pBuff[5] = pBuff[3];
247
248 /* xRight yTop */
249 pBuff[6] = pBuff[4];
250 pBuff[7] = pBuff[1];
251 return &pBuff[8];
252}
253
254DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
255{
256 GLubyte iBase = *piBase;
257 /* triangle 1 */
258 pIndex[0] = iBase;
259 pIndex[1] = iBase + 1;
260 pIndex[2] = iBase + 2;
261
262 /* triangle 2 */
263 pIndex[3] = iBase;
264 pIndex[4] = iBase + 2;
265 pIndex[5] = iBase + 3;
266 *piBase = iBase + 4;
267 return pIndex + 6;
268}
269
270/* Indexed GL_TRIANGLES */
271DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
272{
273 GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
274 return ret;
275}
276
277DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
278{
279 GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
280
281 if (ppIndex)
282 *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
283
284 return ret;
285}
286
287DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
288{
289 return cRects * 4;
290}
291
292#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
293
294DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
295{
296 return 6 * cRects;
297}
298
299
300static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
301{
302 uint32_t i;
303 for (i = 0; i < cRects; ++i)
304 {
305 pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
306 }
307
308
309 if (ppIndex)
310 {
311 GLubyte *pIndex = (GLubyte*)pBuff;
312 *ppIndex = pIndex;
313 for (i = 0; i < cRects; ++i)
314 {
315 pIndex = crBltVtFillRectIndicies(pIndex, piBase);
316 }
317 pBuff = (GLfloat*)pIndex;
318 }
319
320 return pBuff;
321}
322
323static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
324{
325 if (pBuffer->cbBuffer < cbBuffer)
326 {
327 if (pBuffer->pvBuffer)
328 {
329 RTMemFree(pBuffer->pvBuffer);
330 }
331
332#ifndef DEBUG_misha
333 /* debugging: ensure we calculate proper buffer size */
334 cbBuffer += 16;
335#endif
336
337 pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
338 if (pBuffer->pvBuffer)
339 pBuffer->cbBuffer = cbBuffer;
340 else
341 {
342 crWarning("failed to allocate buffer of size %d", cbBuffer);
343 pBuffer->cbBuffer = 0;
344 }
345 }
346 return pBuffer->pvBuffer;
347}
348
349static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
350{
351 bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
352 if (pBlitter->CurrentSetSize.cx != pDstSize->cx
353 || pBlitter->CurrentSetSize.cy != pDstSize->cy)
354 {
355 pBlitter->CurrentSetSize = *pDstSize;
356 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
357 pBlitter->pDispatch->LoadIdentity();
358 pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
359 fUpdateViewport = true;
360 }
361
362 if (fUpdateViewport)
363 {
364 pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
365 pBlitter->Flags.CurrentMuralChanged = 0;
366 }
367
368 pBlitter->Flags.LastWasFBODraw = fFBODraw;
369}
370
371static 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)
372{
373 GLuint normalX, normalY;
374 uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
375 uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
376 Assert(srcHeight == dstHeight);
377
378 switch (pSrc->target)
379 {
380 case GL_TEXTURE_2D:
381 {
382 normalX = pSrc->width;
383 normalY = pSrc->height;
384 break;
385 }
386
387 case GL_TEXTURE_RECTANGLE_ARB:
388 {
389 normalX = 1;
390 normalY = 1;
391 break;
392 }
393
394 default:
395 {
396 crWarning("Unsupported texture target 0x%x", pSrc->target);
397 return VERR_INVALID_PARAMETER;
398 }
399 }
400
401 Assert(pSrc->hwid);
402
403 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
404
405 if (cRects == 1)
406 {
407 /* just optimizatino to draw a single rect with GL_TRIANGLE_FAN */
408 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
409 GLfloat *pVerticies;
410 GLfloat *pTexCoords;
411 GLuint cElements = crBltVtGetNumVerticiesTF(1);
412 if (bUseSameVerticies)
413 {
414 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies));
415 crBltVtRectTFNormalized(paDstRect, normalX, normalY, pVerticies, dstHeight);
416 pTexCoords = pVerticies;
417 }
418 else
419 {
420 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
421 pTexCoords = crBltVtRectTFNormalized(paDstRect, 1, 1, pVerticies, dstHeight);
422 crBltVtRectTFNormalized(paSrcRect, normalX, normalY, pTexCoords, srcHeight);
423 }
424
425 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
426 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
427
428 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
429 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
430
431 pBlitter->pDispatch->Enable(pSrc->target);
432
433 pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
434
435 pBlitter->pDispatch->Disable(pSrc->target);
436
437 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
438 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
439 }
440 else
441 {
442 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
443 GLfloat *pVerticies;
444 GLfloat *pTexCoords;
445 GLubyte *pIndicies;
446 GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
447 GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
448 GLubyte iIdxBase = 0;
449 if (bUseSameVerticies)
450 {
451 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
452 crBltVtRectsITNormalized(paDstRect, cRects, normalX, normalY, pVerticies, &pIndicies, &iIdxBase, dstHeight);
453 pTexCoords = pVerticies;
454 }
455 else
456 {
457 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
458 pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
459 crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
460 }
461
462 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
463 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
464
465 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
466 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
467
468 pBlitter->pDispatch->Enable(pSrc->target);
469
470 pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
471
472 pBlitter->pDispatch->Disable(pSrc->target);
473
474 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
475 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
476 }
477
478 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
479
480 return VINF_SUCCESS;
481}
482
483static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
484{
485 const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
486 if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
487 {
488 pBlitter->Flags.SupportsFBO = 1;
489 pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
490 Assert(pBlitter->idFBO);
491 }
492 else
493 crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
494
495 /* BlitFramebuffer seems to be buggy on Intel,
496 * try always glDrawXxx for now */
497 if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
498 {
499 pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
500 }
501 else
502 {
503// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
504 pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
505 }
506
507 /* defaults. but just in case */
508 pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
509 pBlitter->pDispatch->LoadIdentity();
510 pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
511 pBlitter->pDispatch->LoadIdentity();
512
513 return VINF_SUCCESS;
514}
515
516void CrBltLeave(PCR_BLITTER pBlitter)
517{
518 if (!CrBltIsEntered(pBlitter))
519 {
520 crWarning("CrBltLeave: blitter not entered");
521 return;
522 }
523
524 if (pBlitter->Flags.SupportsFBO)
525 {
526 pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
527 pBlitter->pDispatch->DrawBuffer(GL_BACK);
528 pBlitter->pDispatch->ReadBuffer(GL_BACK);
529 }
530
531 pBlitter->pDispatch->Flush();
532
533 if (pBlitter->CtxInfo.Base.id)
534 {
535 if (pBlitter->pRestoreCtxInfo != &pBlitter->CtxInfo)
536 {
537 pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0, pBlitter->pRestoreCtxInfo->Base.id);
538 }
539 else
540 {
541 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
542 }
543 }
544
545 pBlitter->pRestoreCtxInfo = NULL;
546}
547
548int CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
549{
550 if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
551 {
552 crWarning("current mural not initialized!");
553 return VERR_INVALID_STATE;
554 }
555
556 if (CrBltIsEntered(pBlitter))
557 {
558 crWarning("blitter is entered already!");
559 return VERR_INVALID_STATE;
560 }
561
562 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)*/
563 {
564 if (pRestoreCtxInfo)
565 pBlitter->pDispatch->Flush();
566 pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
567 }
568 else
569 {
570 if (pRestoreCtxInfo)
571 {
572 crWarning("pRestoreCtxInfo is not NULL for \"no-context\" blitter");
573 pRestoreCtxInfo = NULL;
574 }
575 }
576
577 if (pRestoreCtxInfo)
578 {
579 pBlitter->pRestoreCtxInfo = pRestoreCtxInfo;
580 pBlitter->pRestoreMural = pRestoreMural;
581 }
582 else
583 {
584 pBlitter->pRestoreCtxInfo = &pBlitter->CtxInfo;
585 }
586
587 if (pBlitter->Flags.Initialized)
588 return VINF_SUCCESS;
589
590 int rc = crBltInitOnMakeCurent(pBlitter);
591 if (RT_SUCCESS(rc))
592 {
593 pBlitter->Flags.Initialized = 1;
594 return VINF_SUCCESS;
595 }
596
597 crWarning("crBltInitOnMakeCurent failed, rc %d", rc);
598 CrBltLeave(pBlitter);
599 return rc;
600}
601
602static 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)
603{
604 pBlitter->pDispatch->DrawBuffer(enmDstBuff);
605
606 crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
607
608 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
609}
610
611void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
612{
613 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
614 crBltCheckSetupViewport(pBlitter, &DstSize, false);
615}
616
617void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
618{
619 if (!CrBltIsEntered(pBlitter))
620 {
621 crWarning("CrBltBlitTexMural: blitter not entered");
622 return;
623 }
624
625 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
626
627 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
628
629 crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
630}
631
632void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
633{
634 if (!CrBltIsEntered(pBlitter))
635 {
636 crWarning("CrBltBlitTexTex: blitter not entered");
637 return;
638 }
639
640 RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
641
642 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
643
644 /* TODO: mag/min filters ? */
645
646 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
647
648// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
649// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
650
651 crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
652
653 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
654}
655
656void CrBltPresent(PCR_BLITTER pBlitter)
657{
658 if (!CrBltIsEntered(pBlitter))
659 {
660 crWarning("CrBltPresent: blitter not entered");
661 return;
662 }
663
664 if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
665 pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
666 else
667 pBlitter->pDispatch->Flush();
668}
669
670static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
671{
672 memset(pDst, 0, sizeof (*pDst));
673 if (enmFormat != GL_RGBA
674 && enmFormat != GL_BGRA)
675 {
676 crWarning("unsupported format 0x%x", enmFormat);
677 return VERR_NOT_IMPLEMENTED;
678 }
679
680 uint32_t bpp = 32;
681
682 uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
683 uint32_t cbData = pitch * pSrc->height;
684 pDst->pvData = RTMemAllocZ(cbData);
685 if (!pDst->pvData)
686 {
687 crWarning("RTMemAlloc failed");
688 return VERR_NO_MEMORY;
689 }
690
691#ifdef DEBUG_misha
692 {
693 char *pTmp = (char*)pDst->pvData;
694 for (uint32_t i = 0; i < cbData; ++i)
695 {
696 pTmp[i] = (char)((1 << i) % 255);
697 }
698 }
699#endif
700
701 pDst->cbData = cbData;
702 pDst->enmFormat = enmFormat;
703 pDst->width = pSrc->width;
704 pDst->height = pSrc->height;
705 pDst->bpp = bpp;
706 pDst->pitch = pitch;
707 return VINF_SUCCESS;
708}
709
710VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
711{
712 if (!CrBltIsEntered(pBlitter))
713 {
714 crWarning("CrBltImgGetTex: blitter not entered");
715 return VERR_INVALID_STATE;
716 }
717
718 int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
719 if (!RT_SUCCESS(rc))
720 {
721 crWarning("crBltImgCreateForTex failed, rc %d", rc);
722 return rc;
723 }
724 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
725
726#ifdef DEBUG_misha
727 {
728 GLint width = 0, height = 0, depth = 0;
729 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
730 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
731 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
732
733 Assert(width == pSrc->width);
734 Assert(height == pSrc->height);
735// Assert(depth == pSrc->depth);
736 }
737#endif
738
739 pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
740
741 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
742 return VINF_SUCCESS;
743}
744
745VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
746{
747 if (!CrBltIsEntered(pBlitter))
748 {
749 crWarning("CrBltImgGetMural: blitter not entered");
750 return VERR_INVALID_STATE;
751 }
752
753 crWarning("NOT IMPLEMENTED");
754 return VERR_NOT_IMPLEMENTED;
755}
756
757VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
758{
759 if (!CrBltIsEntered(pBlitter))
760 {
761 crWarning("CrBltImgFree: blitter not entered");
762 return;
763 }
764
765 if (pDst->pvData)
766 {
767 RTMemFree(pDst->pvData);
768 pDst->pvData = NULL;
769 }
770}
771
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