VirtualBox

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

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

crOpenGL: always use glDrawXxx for blitting to avoid GPU driver bugs

  • Property svn:executable set to *
File size: 18.8 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
31int CrBltInit(PCR_BLITTER pBlitter, CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, SPUDispatchTable *pDispatch)
32{
33 memset(pBlitter, 0, sizeof (*pBlitter));
34
35 pBlitter->pDispatch = pDispatch;
36
37 if (pCtxBase->Base.id == 0 || pCtxBase->Base.id < -1)
38 {
39 crWarning("Default share context not initialized!");
40 return VERR_INVALID_PARAMETER;
41 }
42
43 pBlitter->CtxInfo = *pCtxBase;
44 if (fCreateNewCtx)
45 {
46 pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
47 if (!pBlitter->CtxInfo.Base.id)
48 {
49 crWarning("CreateContext failed!");
50 return VERR_GENERAL_FAILURE;
51 }
52 pBlitter->Flags.CtxCreated = 1;
53 }
54
55 return VINF_SUCCESS;
56}
57
58void CrBltTerm(PCR_BLITTER pBlitter)
59{
60 if (pBlitter->Flags.CtxCreated)
61 pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
62}
63
64void CrBltMuralSetCurrent(PCR_BLITTER pBlitter, CR_BLITTER_WINDOW *pMural)
65{
66 if (pBlitter->pCurrentMural == pMural)
67 return;
68
69 pBlitter->pCurrentMural = pMural;
70 pBlitter->Flags.CurrentMuralChanged = 1;
71
72 if (!CrBltIsEntered(pBlitter))
73 return;
74
75 if (pMural)
76 pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
77 else
78 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
79}
80
81#define CRBLT_FILTER_FROM_FLAGS(_f) (((_f) & CRBLT_F_LINEAR) ? GL_LINEAR : GL_NEAREST)
82
83static DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const PRTRECTSIZE pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
84{
85 GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
86 pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
87 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
88 pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
89
90 for (uint32_t i = 0; i < cRects; ++i)
91 {
92 const RTRECT * pSrcRect = &paSrcRect[i];
93 const RTRECT * pDstRect = &paDstRect[i];
94 if (CRBLT_F_OFFSCREEN & fFlags)
95 {
96 pBlitter->pDispatch->BlitFramebufferEXT(
97 pSrcRect->xLeft, pSrcRect->yTop, pSrcRect->xRight, pSrcRect->yBottom,
98 pDstRect->xLeft, pDstRect->yTop, pDstRect->xRight, pDstRect->yBottom,
99 GL_COLOR_BUFFER_BIT, filter);
100 }
101 else
102 {
103 int32_t srcY1 = pSrc->height - pSrcRect->yTop;
104 int32_t srcY2 = pSrc->height - pSrcRect->yBottom;
105 int32_t dstY1 = pDstSize->cy - pDstRect->yTop;
106 int32_t dstY2 = pDstSize->cy - pDstRect->yBottom;
107 if (srcY1 > srcY2)
108 {
109 if (dstY1 > dstY2)
110 {
111 /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
112 int32_t tmp = srcY1;
113 srcY1 = srcY2;
114 srcY2 = tmp;
115 tmp = dstY1;
116 dstY1 = dstY2;
117 dstY2 = tmp;
118 }
119 }
120 pBlitter->pDispatch->BlitFramebufferEXT(
121 pSrcRect->xLeft, srcY1, pSrcRect->xRight, srcY2,
122 pDstRect->xLeft, dstY1, pDstRect->xRight, dstY2,
123 GL_COLOR_BUFFER_BIT, filter);
124 }
125 }
126
127 return VINF_SUCCESS;
128}
129
130/* GL_TRIANGLE_FAN */
131DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
132{
133 /* going ccw:
134 * 1. (left;top) 4. (right;top)
135 * | ^
136 * > |
137 * 2. (left;bottom) -> 3. (right;bottom) */
138 /* xLeft yTop */
139 pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
140 pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
141
142 /* xLeft yBottom */
143 pBuff[2] = pBuff[0];
144 pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
145
146 /* xRight yBottom */
147 pBuff[4] = ((float)pRect->xRight)/((float)normalX);
148 pBuff[5] = pBuff[3];
149
150 /* xRight yTop */
151 pBuff[6] = pBuff[4];
152 pBuff[7] = pBuff[1];
153 return &pBuff[8];
154}
155
156DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
157{
158 /* xLeft yTop */
159 pBuff[0] = pRect->xLeft;
160 pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
161
162 /* xLeft yBottom */
163 pBuff[2] = pBuff[0];
164 pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
165
166 /* xRight yBottom */
167 pBuff[4] = pRect->xRight;
168 pBuff[5] = pBuff[3];
169
170 /* xRight yTop */
171 pBuff[6] = pBuff[4];
172 pBuff[7] = pBuff[1];
173 return &pBuff[8];
174}
175
176DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
177{
178 GLubyte iBase = *piBase;
179 /* triangle 1 */
180 pIndex[0] = iBase;
181 pIndex[1] = iBase + 1;
182 pIndex[2] = iBase + 2;
183
184 /* triangle 2 */
185 pIndex[3] = iBase;
186 pIndex[4] = iBase + 2;
187 pIndex[5] = iBase + 3;
188 *piBase = iBase + 4;
189 return pIndex + 6;
190}
191
192/* Indexed GL_TRIANGLES */
193DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
194{
195 GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
196 return ret;
197}
198
199DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
200{
201 GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
202
203 if (ppIndex)
204 *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
205
206 return ret;
207}
208
209DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
210{
211 return cRects * 4;
212}
213
214#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
215
216DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
217{
218 return 6 * cRects;
219}
220
221
222static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
223{
224 uint32_t i;
225 for (i = 0; i < cRects; ++i)
226 {
227 pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
228 }
229
230
231 if (ppIndex)
232 {
233 GLubyte *pIndex = (GLubyte*)pBuff;
234 *ppIndex = pIndex;
235 for (i = 0; i < cRects; ++i)
236 {
237 pIndex = crBltVtFillRectIndicies(pIndex, piBase);
238 }
239 pBuff = (GLfloat*)pIndex;
240 }
241
242 return pBuff;
243}
244
245static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
246{
247 if (pBuffer->cbBuffer < cbBuffer)
248 {
249 if (pBuffer->pvBuffer)
250 {
251 RTMemFree(pBuffer->pvBuffer);
252 }
253
254#ifndef DEBUG_misha
255 /* debugging: ensure we calculate proper buffer size */
256 cbBuffer += 16;
257#endif
258
259 pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
260 if (pBuffer->pvBuffer)
261 pBuffer->cbBuffer = cbBuffer;
262 else
263 {
264 crWarning("failed to allocate buffer of size %d", cbBuffer);
265 pBuffer->cbBuffer = 0;
266 }
267 }
268 return pBuffer->pvBuffer;
269}
270
271static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const PRTRECTSIZE pDstSize, bool fFBODraw)
272{
273 if (!pBlitter->Flags.LastWasFBODraw != !fFBODraw
274 || pBlitter->Flags.CurrentMuralChanged
275 || pBlitter->CurrentSetSize.cx != pDstSize->cx
276 || pBlitter->CurrentSetSize.cy != pDstSize->cy)
277 {
278#if 0
279 const GLdouble aProjection[] =
280 {
281 2.0 / pDstSize->cx, 0.0, 0.0, 0.0,
282 0.0, 2.0 / pDstSize->cy, 0.0, 0.0,
283 0.0, 0.0, 2.0, 0.0,
284 -1.0, -1.0, -1.0, 1.0
285 };
286 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
287 pBlitter->pDispatch->LoadMatrixd(aProjection);
288 pBlitter->pDispatch->Viewport(0, 0, pDstSize->cx, pDstSize->cy);
289#else
290 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
291 pBlitter->pDispatch->LoadIdentity();
292 pBlitter->pDispatch->Viewport(0, 0, pDstSize->cx, pDstSize->cy);
293 pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
294 pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
295 pBlitter->pDispatch->LoadIdentity();
296 pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
297 pBlitter->pDispatch->LoadIdentity();
298
299 /* Clear background to transparent */
300 pBlitter->pDispatch->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
301#endif
302 pBlitter->CurrentSetSize.cx = pDstSize->cx;
303 pBlitter->CurrentSetSize.cy = pDstSize->cy;
304 pBlitter->Flags.LastWasFBODraw = fFBODraw;
305 if (!fFBODraw)
306 pBlitter->Flags.CurrentMuralChanged = 0;
307 }
308}
309
310static DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const PRTRECTSIZE pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
311{
312 GLuint normalX, normalY;
313 uint32_t height = (fFlags & CRBLT_F_OFFSCREEN) ? 0 : pDstSize->cy;
314
315 switch (pSrc->target)
316 {
317 case GL_TEXTURE_2D:
318 {
319 normalX = pSrc->width;
320 normalY = pSrc->height;
321 break;
322 }
323
324 case GL_TEXTURE_RECTANGLE_ARB:
325 {
326 normalX = 1;
327 normalY = 1;
328 break;
329 }
330
331 default:
332 {
333 crWarning("Unsupported texture target 0x%x", pSrc->target);
334 return VERR_INVALID_PARAMETER;
335 }
336 }
337
338 Assert(pSrc->hwid);
339
340 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
341
342 if (cRects == 1)
343 {
344 /* just optimizatino to draw a single rect with GL_TRIANGLE_FAN */
345 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1;
346 GLfloat *pVerticies;
347 GLfloat *pTexCoords;
348 GLuint cElements = crBltVtGetNumVerticiesTF(1);
349 if (bUseSameVerticies)
350 {
351 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies));
352 crBltVtRectTFNormalized(paDstRect, normalX, normalY, pVerticies, height);
353 pTexCoords = pVerticies;
354 }
355 else
356 {
357 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
358 pTexCoords = crBltVtRectTFNormalized(paDstRect, 1, 1, pVerticies, height);
359 crBltVtRectTFNormalized(paSrcRect, normalX, normalY, pTexCoords, height);
360 }
361
362 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
363 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
364
365 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
366 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
367
368 pBlitter->pDispatch->Enable(pSrc->target);
369
370 pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
371
372 pBlitter->pDispatch->Disable(pSrc->target);
373
374 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
375 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
376 }
377 else
378 {
379 bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1;
380 GLfloat *pVerticies;
381 GLfloat *pTexCoords;
382 GLubyte *pIndicies;
383 GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
384 GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
385 GLubyte iIdxBase = 0;
386 if (bUseSameVerticies)
387 {
388 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
389 crBltVtRectsITNormalized(paDstRect, cRects, normalX, normalY, pVerticies, &pIndicies, &iIdxBase, height);
390 pTexCoords = pVerticies;
391 }
392 else
393 {
394 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
395 pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, height);
396 crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, height);
397 }
398
399 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
400 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
401
402 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
403 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
404
405 pBlitter->pDispatch->Enable(pSrc->target);
406
407 pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
408
409 pBlitter->pDispatch->Disable(pSrc->target);
410
411 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
412 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
413 }
414
415 return VINF_SUCCESS;
416}
417
418static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
419{
420 const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
421 if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
422 {
423 pBlitter->Flags.SupportsFBO = 1;
424 pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
425 Assert(pBlitter->idFBO);
426 }
427 else
428 crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
429
430 /* BlitFramebuffer seems to be buggy on Intel,
431 * try always glDrawXxx for now */
432 if (0 && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
433 {
434 pBlitter->Flags.SupportsFBOBlit = 1;
435 pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
436 }
437 else
438 {
439// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
440 pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
441 }
442
443 return VINF_SUCCESS;
444}
445
446void CrBltLeave(PCR_BLITTER pBlitter)
447{
448 Assert(CrBltIsEntered(pBlitter));
449
450 if (pBlitter->Flags.SupportsFBO)
451 {
452 pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
453 pBlitter->pDispatch->DrawBuffer(GL_BACK);
454 pBlitter->pDispatch->ReadBuffer(GL_BACK);
455 }
456
457 pBlitter->pDispatch->Flush();
458
459 if (pBlitter->pRestoreCtxInfo != &pBlitter->CtxInfo)
460 {
461
462 pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0,
463 pBlitter->pRestoreCtxInfo->Base.id >= 0
464 ? pBlitter->pRestoreCtxInfo->Base.id : pBlitter->pRestoreCtxInfo->Base.id);
465 }
466 else
467 {
468 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
469 }
470
471 pBlitter->pRestoreCtxInfo = NULL;
472}
473
474int CrBltEnter(PCR_BLITTER pBlitter, CR_BLITTER_CONTEXT *pRestoreCtxInfo, CR_BLITTER_WINDOW *pRestoreMural)
475{
476 if (!pBlitter->pCurrentMural)
477 {
478 crWarning("current mural not initialized!");
479 return VERR_INVALID_STATE;
480 }
481
482 if (CrBltIsEntered(pBlitter))
483 {
484 crWarning("blitter is entered already!");
485 return VERR_INVALID_STATE;
486 }
487
488 if (pRestoreCtxInfo)
489 {
490 pBlitter->pRestoreCtxInfo = pRestoreCtxInfo;
491 pBlitter->pRestoreMural = pRestoreMural;
492
493 pBlitter->pDispatch->Flush();
494 }
495 else
496 {
497 pBlitter->pRestoreCtxInfo = &pBlitter->CtxInfo;
498 }
499
500 pBlitter->pDispatch->MakeCurrent(pBlitter->pCurrentMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
501
502 if (pBlitter->Flags.Initialized)
503 return VINF_SUCCESS;
504
505 int rc = crBltInitOnMakeCurent(pBlitter);
506 if (RT_SUCCESS(rc))
507 {
508 pBlitter->Flags.Initialized = 1;
509 return VINF_SUCCESS;
510 }
511
512 crWarning("crBltInitOnMakeCurent failed, rc %d", rc);
513 CrBltLeave(pBlitter);
514 return rc;
515}
516
517static void crBltBlitTexBuf(PCR_BLITTER pBlitter, VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const PRTRECTSIZE pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
518{
519 pBlitter->pDispatch->DrawBuffer(enmDstBuff);
520
521 crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
522
523 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags & CRBLT_F_OFFSCREEN);
524}
525
526void CrBltBlitTexMural(PCR_BLITTER pBlitter, VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
527{
528 RTRECTSIZE DstSize = {pBlitter->pCurrentMural->width, pBlitter->pCurrentMural->height};
529
530 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
531
532 crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, GL_BACK, &DstSize, paDstRects, cRects, fFlags & (~CRBLT_F_OFFSCREEN));
533}
534
535void CrBltBlitTexTex(PCR_BLITTER pBlitter, VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
536{
537 RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
538
539 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
540
541 /* TODO: mag/min filters ? */
542
543 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
544
545// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
546// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
547
548 crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
549}
550
551void CrBltPresent(PCR_BLITTER pBlitter)
552{
553 if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
554 pBlitter->pDispatch->SwapBuffers(pBlitter->pCurrentMural->Base.id, 0);
555 else
556 pBlitter->pDispatch->Flush();
557}
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