VirtualBox

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

Last change on this file since 78292 was 78190, checked in by vboxsync, 6 years ago

Merge first stage of the Chromium cleanup from the branch:

  • r129818 (Remove VBOX_WITH_CR_DISPLAY_LISTS and accompanying code as it was disabled since r108676 and was never brought back (see ​bugref:3456 and ​bugref:8485))
  • r129819 (HostServices/SharedOpenGL: Remove unused main entry point from upstream server process based implementation)
  • r129820 (HostServices/SharedOpenGL: Started eliminating all backends other than HGCM. They are not used and probably wouldn't work anymore anyway)
  • r129821 (HostServices/SharedOpenGL,GuestHost/OpenGLAdditions/common/crOpenGL: Kill crTimer* API as it is not used anywhere)
  • r129822 (HostServices/SharedOpenGL,GuestHost/OpenGLAdditions/common/crOpenGL: Kill most from cr_process.h apart from two used methods)
  • r129823 (HostServices/SharedOpenGL,GuestHost/OpenGLAdditions/common/crOpenGL: Kill crList* API as it is unused)
  • r129824 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Kill crHullInteriorBox API as it is unused)
  • r129825 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Kill crWarpPoint API as it is unused)
  • r129826 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Kill CrSa* API as it is unused and not even compiled in)
  • r129827 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Kill cr_bbox.h as it is unused)
  • r129828 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove a few crParseUrl() two uses)
  • r129829 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove last crParseURL() use)
  • r129830 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove crParseURL())
  • r129831 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove VBOX_WITH_COCOA_QT and related code when not set as it is the default for years now and we don't support anything else anymore)
  • r129832 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused cr_logo.h)
  • r129833 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused crut_api.h and crut_clientapi.h)
  • r129834 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused cr_dmx.h)
  • r129835 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused cr_perf.h)
  • r129836 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove cr_rand.h and friends as it is not actively used anywhere)
  • r129837 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of all the swapped versions in the packer SPU, we never change endianess from guest to host and don't need it)
  • r129838 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove more swapper versions in the packer related code)
  • r129839 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove more swapper versions in the packer related code)
  • r129840 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused pack_pica.c)
  • r129841 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove more swapper versions in the packer related code)
  • r129842 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of cr_endianess.h and friends)
  • r129843 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of unused lowercase.py)
  • r129844 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of unused cr_calllists.h and friends)
  • r129845 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of completely unused idpool.c, not even compiled in)
  • r129846 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of unused cr_debugopcodes.h and friends)
  • r129847 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Make the cr_mem.h API inline and get rid of the implementation in the util library)
  • r129848 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of SPUOptions and related code as it is of no use for us)
  • r129849 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of cr_environment.h and friends and convert usage to RTEnv* APIs)
  • r129850 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of unused renderspu_agl.c)
  • r129851 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Remove unused code in cr_htable.h)
  • r129853 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Introduce a state paremeter for the unpacker workers instead of reyling on global variables, work in progress)
  • r129854 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Let the caller of crUnpack set up the initial state. This allows to get rid of the global return_ptr and writeback_ptr as they get supplied in the unpacker state by the server)
  • r129855 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of the cr_lastDispatch and cr_unpackDispatch as they are of no use now)
  • r129856 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Get rid of the global cr_unpackData and cr_unpackDataEnd symbols by indtroducing another hack to make it possible for certail server dispatch callbacks to access the data buffer)
  • r129857 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: build fix for release builds)
  • r129858 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Make the pointer to the unpacker state non const (is required for the access verification))
  • r129859 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: First iteration of the buffer size validation to prevent out of bound read access + added todos for places where additional checks are needed)
  • r129860 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Working on remaining verification todos)
  • r129861 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Working on remaining verification todos)
  • r129871 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Working on remaining verification todos)
  • r129872 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Stop as soon as the unpacker encountered an error)
  • r129876 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Working on remaining verification todos)
  • r129880 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Working on remaining verification todos)
  • r129882 (HostServices/SharedOpenGL,GuestHost/OpenGL,Additions/common/crOpenGL: Fixed some offsets in unpack_texture.c, 3DMark03 renders correctly again)
  • r130013 (HostServices/SharedOpenGL: Convert files to C++ so we can use C99 featuers on Windows with cl.exe)
  • r130014 (HostServices/SharedOpenGL,GuestHost/OpenGL: WIndows build fixes)
  • r130015 (HostServices/SharedOpenGL,GuestHost/OpenGL: More Windows build fixes)
  • r130036 (Config.kmk: Fix linker error on Windows by temporarily disabling the use of VBoxGuestR3DllMinW2K)
  • r130094 (src/VBox/GuestHost/OpenGL: Revert inlining the allocation/free functions in R3 completely as it doesn't work on Windows if memory is allocated and freed across different DLLs which don't share a common CRT, causes crashes in RtlValidtaeHeap())
  • r130095 (src/VBox/GuestHost/OpenGL,src/VBox/Additions/common/crOpenGL/pack: Don't use floating point specifiers in packspu_GetString() to avoid R6002 errors (couldn't fully understand why they occur suddenly after the rework but this gets rid of it))
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.2 KB
Line 
1/* $Id: blitter.cpp 78190 2019-04-18 00:07:07Z vboxsync $ */
2/** @file
3 * Blitter API implementation
4 */
5
6/*
7 * Copyright (C) 2013-2019 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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#ifdef IN_VMSVGA3D
23# include <OpenGL/OpenGL.h>
24# include <OpenGL/gl3.h>
25# include "../include/cr_blitter.h"
26# include <iprt/assert.h>
27# define WARN AssertMsgFailed
28# define CRASSERT Assert
29DECLINLINE(void) crWarning(const char *format, ... ) {}
30#else
31# include "cr_blitter.h"
32# include "cr_spu.h"
33# include "chromium.h"
34# include "cr_error.h"
35# include "cr_net.h"
36# include "cr_mem.h"
37# include "cr_string.h"
38# include "cr_bmpscale.h"
39#endif
40
41#include <iprt/errcore.h>
42#include <iprt/mem.h>
43
44
45
46static void crMClrFillMem(uint32_t *pu32Dst, int32_t cbDstPitch, uint32_t width, uint32_t height, uint32_t u32Color)
47{
48 for (uint32_t i = 0; i < height; ++i)
49 {
50 for (uint32_t j = 0; j < width; ++j)
51 {
52 pu32Dst[j] = u32Color;
53 }
54
55 pu32Dst = (uint32_t*)(((uint8_t*)pu32Dst) + cbDstPitch);
56 }
57}
58
59void CrMClrFillImgRect(CR_BLITTER_IMG *pDst, const RTRECT *pCopyRect, uint32_t u32Color)
60{
61 int32_t x = pCopyRect->xLeft;
62 int32_t y = pCopyRect->yTop;
63 int32_t width = pCopyRect->xRight - pCopyRect->xLeft;
64 int32_t height = pCopyRect->yBottom - pCopyRect->yTop;
65 Assert(x >= 0);
66 Assert(y >= 0);
67 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * y + x * 4;
68
69 crMClrFillMem((uint32_t*)pu8Dst, pDst->pitch, width, height, u32Color);
70}
71
72void CrMClrFillImg(CR_BLITTER_IMG *pImg, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
73{
74 RTRECT Rect;
75 Rect.xLeft = 0;
76 Rect.yTop = 0;
77 Rect.xRight = pImg->width;
78 Rect.yBottom = pImg->height;
79
80
81 RTRECT Intersection;
82 /*const RTPOINT ZeroPoint = {0, 0}; - unused */
83
84 for (uint32_t i = 0; i < cRects; ++i)
85 {
86 const RTRECT * pRect = &pRects[i];
87 VBoxRectIntersected(pRect, &Rect, &Intersection);
88
89 if (VBoxRectIsZero(&Intersection))
90 continue;
91
92 CrMClrFillImgRect(pImg, &Intersection, u32Color);
93 }
94}
95
96static void crMBltMem(const uint8_t *pu8Src, int32_t cbSrcPitch, uint8_t *pu8Dst, int32_t cbDstPitch, uint32_t width, uint32_t height)
97{
98 uint32_t cbCopyRow = width * 4;
99
100 for (uint32_t i = 0; i < height; ++i)
101 {
102 memcpy(pu8Dst, pu8Src, cbCopyRow);
103
104 pu8Src += cbSrcPitch;
105 pu8Dst += cbDstPitch;
106 }
107}
108
109void CrMBltImgRect(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, CR_BLITTER_IMG *pDst)
110{
111 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
112 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
113 Assert(srcX >= 0);
114 Assert(srcY >= 0);
115 Assert(srcX < (int32_t)pSrc->width);
116 Assert(srcY < (int32_t)pSrc->height);
117
118 int32_t dstX = pCopyRect->xLeft;
119 int32_t dstY = pCopyRect->yTop;
120 Assert(dstX >= 0);
121 Assert(dstY >= 0);
122 Assert(dstX < (int32_t)pDst->width);
123 Assert(dstY < (int32_t)pDst->height);
124
125 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
126 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
127
128 crMBltMem(pu8Src, fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
129}
130
131void CrMBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
132{
133 RTRECT Intersection;
134 RTRECT RestrictSrcRect;
135 RestrictSrcRect.xLeft = 0;
136 RestrictSrcRect.yTop = 0;
137 RestrictSrcRect.xRight = pSrc->width;
138 RestrictSrcRect.yBottom = pSrc->height;
139 RTRECT RestrictDstRect;
140 RestrictDstRect.xLeft = 0;
141 RestrictDstRect.yTop = 0;
142 RestrictDstRect.xRight = pDst->width;
143 RestrictDstRect.yBottom = pDst->height;
144
145 for (uint32_t i = 0; i < cRects; ++i)
146 {
147 const RTRECT * pRect = &pRects[i];
148 VBoxRectIntersected(pRect, &RestrictDstRect, &Intersection);
149
150 RTRECT TranslatedSrc;
151 VBoxRectTranslated(&RestrictSrcRect, pPos->x, pPos->y, &TranslatedSrc);
152
153 VBoxRectIntersect(&Intersection, &TranslatedSrc);
154
155 if (VBoxRectIsZero(&Intersection))
156 continue;
157
158 CrMBltImgRect(pSrc, pPos, false, &Intersection, pDst);
159 }
160}
161
162#ifndef IN_VMSVGA3D
163
164void CrMBltImgRectScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pPos, bool fSrcInvert, const RTRECT *pCopyRect, float strX, float strY, CR_BLITTER_IMG *pDst)
165{
166 RTPOINT UnscaledPos;
167 UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pPos->x / strX);
168 UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pPos->y / strY);
169
170 RTRECT UnscaledCopyRect;
171
172 VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect);
173
174 if (VBoxRectIsZero(&UnscaledCopyRect))
175 {
176 WARN(("ups"));
177 return;
178 }
179
180 int32_t srcX = UnscaledCopyRect.xLeft - UnscaledPos.x;
181 int32_t srcY = UnscaledCopyRect.yTop - UnscaledPos.y;
182 if (srcX < 0)
183 {
184 WARN(("ups"));
185 srcX = 0;
186 }
187 if (srcY < 0)
188 {
189 WARN(("ups"));
190 srcY = 0;
191 }
192
193 if ((GLuint)srcX >= pSrc->width)
194 {
195 WARN(("ups"));
196 return;
197 }
198
199 if ((GLuint)srcY >= pSrc->height)
200 {
201 WARN(("ups"));
202 return;
203 }
204
205 Assert(srcX >= 0);
206 Assert(srcY >= 0);
207 Assert(srcX < (int32_t)pSrc->width);
208 Assert(srcY < (int32_t)pSrc->height);
209
210 int32_t dstX = pCopyRect->xLeft;
211 int32_t dstY = pCopyRect->yTop;
212 Assert(dstX >= 0);
213 Assert(dstY >= 0);
214
215 int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft;
216 int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop;
217
218 if (UnscaledSrcWidth + srcX > (GLint)pSrc->width)
219 UnscaledSrcWidth = pSrc->width - srcX;
220
221 if (UnscaledSrcHeight + srcY > (GLint)pSrc->height)
222 UnscaledSrcHeight = pSrc->height - srcY;
223
224 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
225 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
226
227 CrBmpScale32(pu8Dst, pDst->pitch,
228 pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop,
229 pu8Src,
230 fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch,
231 UnscaledSrcWidth, UnscaledSrcHeight);
232}
233
234
235void CrMBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
236{
237 int32_t srcWidth = pSrcRectSize->cx;
238 int32_t srcHeight = pSrcRectSize->cy;
239 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
240 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
241
242 float strX = ((float)dstWidth) / srcWidth;
243 float strY = ((float)dstHeight) / srcHeight;
244 Assert(dstWidth != srcWidth || dstHeight != srcHeight);
245
246 RTRECT Intersection;
247 RTRECT ScaledRestrictSrcRect;
248 ScaledRestrictSrcRect.xLeft = 0;
249 ScaledRestrictSrcRect.yTop = 0;
250 ScaledRestrictSrcRect.xRight = CR_FLOAT_RCAST(int32_t, pSrc->width * strX);
251 ScaledRestrictSrcRect.yBottom = CR_FLOAT_RCAST(int32_t, pSrc->height * strY);
252 RTRECT RestrictDstRect;
253 RestrictDstRect.xLeft = 0;
254 RestrictDstRect.yTop = 0;
255 RestrictDstRect.xRight = pDst->width;
256 RestrictDstRect.yBottom = pDst->height;
257
258 RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
259
260 for (uint32_t i = 0; i < cRects; ++i)
261 {
262 const RTRECT * pRect = &pRects[i];
263 VBoxRectIntersected(pRect, &RestrictDstRect, &Intersection);
264
265 RTRECT TranslatedSrc;
266 VBoxRectTranslated(&ScaledRestrictSrcRect, Pos.x, Pos.y, &TranslatedSrc);
267
268 VBoxRectIntersect(&Intersection, &TranslatedSrc);
269
270 if (VBoxRectIsZero(&Intersection))
271 continue;
272
273 CrMBltImgRectScaled(pSrc, &Pos, false, &Intersection, strX, strY, pDst);
274 }
275}
276
277#endif /* !IN_VMSVGA3D */
278
279
280/**
281 *
282 * @param pBlitter The blitter to initialize.
283 * @param pCtxBase Contains the blitter context info. Its value is
284 * treated differently depending on the fCreateNewCtx
285 * value.
286 * @param fCreateNewCtx If true, then @a pCtxBase must NOT be NULL. Its
287 * visualBits is used as a visual bits info for the new
288 * context, its id field is used to specified the
289 * shared context id to be used for blitter context.
290 * The id can be null to specify no shared context is
291 * needed
292 *
293 * If false and @a pCtxBase is NOT null AND its id
294 * field is NOT null, then specified the blitter
295 * context to be used blitter treats it as if it has
296 * default ogl state.
297 *
298 * Otherwise, the blitter works in a "no-context" mode,
299 * i.e. the caller is responsible for making a proper
300 * context current before calling the blitter. Note
301 * that BltEnter/Leave MUST still be called, but the
302 * proper context must be set before doing BltEnter,
303 * and ResoreContext info is ignored in that case. Also
304 * note that the blitter caches the current window
305 * info, and assumes the current context's values are
306 * preserved wrt that window before the calls, so if
307 * one uses different contexts for one blitter, the
308 * blitter current window values must be explicitly
309 * reset by doing CrBltMuralSetCurrentInfo(pBlitter,
310 * NULL).
311 * @param fForceDrawBlt If true this forces the blitter to always use
312 * glDrawXxx-based blits even if
313 * GL_EXT_framebuffer_blit. This is needed because
314 * BlitFramebufferEXT is often known to be buggy, and
315 * glDrawXxx-based blits appear to be more reliable.
316 * @param pShaders
317 * @param pDispatch
318 */
319VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase,
320 bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders,
321 SPUDispatchTable *pDispatch)
322{
323 if (pCtxBase && pCtxBase->Base.id < 0)
324 {
325 crWarning("Default share context not initialized!");
326 return VERR_INVALID_PARAMETER;
327 }
328
329 if (!pCtxBase && fCreateNewCtx)
330 {
331 crWarning("pCtxBase is zero while fCreateNewCtx is set!");
332 return VERR_INVALID_PARAMETER;
333 }
334
335 RT_ZERO(*pBlitter);
336
337 pBlitter->pDispatch = pDispatch;
338 if (pCtxBase)
339 pBlitter->CtxInfo = *pCtxBase;
340
341 pBlitter->Flags.ForceDrawBlit = fForceDrawBlt;
342
343 if (fCreateNewCtx)
344 {
345#ifdef IN_VMSVGA3D
346 /** @todo IN_VMSVGA3D */
347 pBlitter->CtxInfo.Base.id = 0;
348#else
349 pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
350#endif
351 if (!pBlitter->CtxInfo.Base.id)
352 {
353 RT_ZERO(*pBlitter);
354 crWarning("CreateContext failed!");
355 return VERR_GENERAL_FAILURE;
356 }
357 pBlitter->Flags.CtxCreated = 1;
358 }
359
360 if (pShaders)
361 {
362 pBlitter->pGlslCache = pShaders;
363 pBlitter->Flags.ShadersGloal = 1;
364 }
365 else
366 {
367 CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
368 pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
369 }
370
371 return VINF_SUCCESS;
372}
373
374VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter)
375{
376 if (CrBltIsEntered(pBlitter))
377 {
378 WARN(("CrBltBlitTexTex: blitter is entered"));
379 return VERR_INVALID_STATE;
380 }
381
382 if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
383 return VINF_SUCCESS;
384
385 int rc = CrBltEnter(pBlitter);
386 if (!RT_SUCCESS(rc))
387 {
388 WARN(("CrBltEnter failed, rc %d", rc));
389 return rc;
390 }
391
392 CrGlslCleanup(&pBlitter->LocalGlslCache);
393
394 CrBltLeave(pBlitter);
395
396 return VINF_SUCCESS;
397}
398
399void CrBltTerm(PCR_BLITTER pBlitter)
400{
401#ifdef IN_VMSVGA3D
402 /** @todo IN_VMSVGA3D */
403#else
404 if (pBlitter->Flags.CtxCreated)
405 pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
406#endif
407 memset(pBlitter, 0, sizeof (*pBlitter));
408}
409
410int CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
411{
412 if (pMural)
413 {
414 if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
415 return VINF_SUCCESS;
416 memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
417 }
418 else
419 {
420 if (CrBltIsEntered(pBlitter))
421 {
422 WARN(("can not set null mural for entered bleater"));
423 return VERR_INVALID_STATE;
424 }
425 if (!pBlitter->CurrentMural.Base.id)
426 return VINF_SUCCESS;
427 pBlitter->CurrentMural.Base.id = 0;
428 }
429
430 pBlitter->Flags.CurrentMuralChanged = 1;
431
432 if (!CrBltIsEntered(pBlitter))
433 return VINF_SUCCESS;
434
435 if (!pBlitter->CtxInfo.Base.id)
436 {
437 WARN(("setting current mural for entered no-context blitter"));
438 return VERR_INVALID_STATE;
439 }
440
441 WARN(("changing mural for entered blitter, is is somewhat expected?"));
442
443#ifdef IN_VMSVGA3D
444 /** @todo IN_VMSVGA3D */
445#else
446 pBlitter->pDispatch->Flush();
447
448 pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
449#endif
450
451 return VINF_SUCCESS;
452}
453
454
455#ifndef IN_VMSVGA3D
456
457static 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)
458{
459 GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
460 pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
461 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
462 pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
463
464 for (uint32_t i = 0; i < cRects; ++i)
465 {
466 const RTRECT * pSrcRect = &paSrcRect[i];
467 const RTRECT * pDstRect = &paDstRect[i];
468 int32_t srcY1;
469 int32_t srcY2;
470 int32_t dstY1;
471 int32_t dstY2;
472 int32_t srcX1 = pSrcRect->xLeft;
473 int32_t srcX2 = pSrcRect->xRight;
474 int32_t dstX1 = pDstRect->xLeft;
475 int32_t dstX2 = pDstRect->xRight;
476
477 if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
478 {
479 srcY1 = pSrc->height - pSrcRect->yTop;
480 srcY2 = pSrc->height - pSrcRect->yBottom;
481 }
482 else
483 {
484 srcY1 = pSrcRect->yTop;
485 srcY2 = pSrcRect->yBottom;
486 }
487
488 if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
489 {
490 dstY1 = pDstSize->cy - pDstRect->yTop;
491 dstY2 = pDstSize->cy - pDstRect->yBottom;
492 }
493 else
494 {
495 dstY1 = pDstRect->yTop;
496 dstY2 = pDstRect->yBottom;
497 }
498
499 if (srcY1 > srcY2)
500 {
501 if (dstY1 > dstY2)
502 {
503 /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
504 int32_t tmp = srcY1;
505 srcY1 = srcY2;
506 srcY2 = tmp;
507 tmp = dstY1;
508 dstY1 = dstY2;
509 dstY2 = tmp;
510 }
511 }
512
513 if (srcX1 > srcX2)
514 {
515 if (dstX1 > dstX2)
516 {
517 /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
518 int32_t tmp = srcX1;
519 srcX1 = srcX2;
520 srcX2 = tmp;
521 tmp = dstX1;
522 dstX1 = dstX2;
523 dstX2 = tmp;
524 }
525 }
526
527 pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
528 dstX1, dstY1, dstX2, dstY2,
529 GL_COLOR_BUFFER_BIT, filter);
530 }
531
532 return VINF_SUCCESS;
533}
534
535/* GL_TRIANGLE_FAN */
536DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
537{
538 /* going ccw:
539 * 1. (left;top) 4. (right;top)
540 * | ^
541 * > |
542 * 2. (left;bottom) -> 3. (right;bottom) */
543 /* xLeft yTop */
544 pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
545 pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
546
547 /* xLeft yBottom */
548 pBuff[2] = pBuff[0];
549 pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
550
551 /* xRight yBottom */
552 pBuff[4] = ((float)pRect->xRight)/((float)normalX);
553 pBuff[5] = pBuff[3];
554
555 /* xRight yTop */
556 pBuff[6] = pBuff[4];
557 pBuff[7] = pBuff[1];
558 return &pBuff[8];
559}
560
561DECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
562{
563 for (uint32_t i = 0; i < cRects; ++i)
564 {
565 pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
566 }
567 return pBuff;
568}
569
570DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
571{
572 (void)normalX; (void)normalY;
573
574 /* xLeft yTop */
575 pBuff[0] = pRect->xLeft;
576 pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
577
578 /* xLeft yBottom */
579 pBuff[2] = pBuff[0];
580 pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
581
582 /* xRight yBottom */
583 pBuff[4] = pRect->xRight;
584 pBuff[5] = pBuff[3];
585
586 /* xRight yTop */
587 pBuff[6] = pBuff[4];
588 pBuff[7] = pBuff[1];
589 return &pBuff[8];
590}
591
592DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
593{
594 GLubyte iBase = *piBase;
595 /* triangle 1 */
596 pIndex[0] = iBase;
597 pIndex[1] = iBase + 1;
598 pIndex[2] = iBase + 2;
599
600 /* triangle 2 */
601 pIndex[3] = iBase;
602 pIndex[4] = iBase + 2;
603 pIndex[5] = iBase + 3;
604 *piBase = iBase + 4;
605 return pIndex + 6;
606}
607
608/* Indexed GL_TRIANGLES */
609DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
610{
611 GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
612 return ret;
613}
614
615DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
616{
617 GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
618
619 if (ppIndex)
620 *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
621
622 return ret;
623}
624
625DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
626{
627 return cRects * 4;
628}
629
630#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
631
632DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
633{
634 return 6 * cRects;
635}
636
637
638static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
639{
640 uint32_t i;
641 for (i = 0; i < cRects; ++i)
642 {
643 pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
644 }
645
646
647 if (ppIndex)
648 {
649 GLubyte *pIndex = (GLubyte*)pBuff;
650 *ppIndex = pIndex;
651 for (i = 0; i < cRects; ++i)
652 {
653 pIndex = crBltVtFillRectIndicies(pIndex, piBase);
654 }
655 pBuff = (GLfloat*)pIndex;
656 }
657
658 return pBuff;
659}
660
661static void *crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
662{
663 if (pBuffer->cbBuffer < cbBuffer)
664 {
665 if (pBuffer->pvBuffer)
666 {
667 RTMemFree(pBuffer->pvBuffer);
668 }
669
670#ifndef DEBUG_misha
671 /* debugging: ensure we calculate proper buffer size */
672 cbBuffer += 16;
673#endif
674
675 pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
676 if (pBuffer->pvBuffer)
677 pBuffer->cbBuffer = cbBuffer;
678 else
679 {
680 crWarning("failed to allocate buffer of size %d", cbBuffer);
681 pBuffer->cbBuffer = 0;
682 }
683 }
684 return pBuffer->pvBuffer;
685}
686
687#endif /* !IN_VMSVGA3D */
688
689
690static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
691{
692 bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
693 if ( pBlitter->CurrentSetSize.cx != pDstSize->cx
694 || pBlitter->CurrentSetSize.cy != pDstSize->cy)
695 {
696 pBlitter->CurrentSetSize = *pDstSize;
697#ifdef IN_VMSVGA3D
698 /** @todo IN_VMSVGA3D */
699#else
700 pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
701 pBlitter->pDispatch->LoadIdentity();
702 pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
703#endif
704 fUpdateViewport = true;
705 }
706
707 if (fUpdateViewport)
708 {
709#ifdef IN_VMSVGA3D
710 /** @todo IN_VMSVGA3D */
711#else
712 pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
713#endif
714 pBlitter->Flags.CurrentMuralChanged = 0;
715 }
716
717 pBlitter->Flags.LastWasFBODraw = fFBODraw;
718}
719
720
721#ifndef IN_VMSVGA3D
722
723static 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)
724{
725 GLuint normalX, normalY;
726 uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
727 uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
728
729 switch (pSrc->target)
730 {
731 case GL_TEXTURE_2D:
732 {
733 normalX = pSrc->width;
734 normalY = pSrc->height;
735 break;
736 }
737
738 case GL_TEXTURE_RECTANGLE_ARB:
739 {
740 normalX = 1;
741 normalY = 1;
742 break;
743 }
744
745 default:
746 {
747 crWarning("Unsupported texture target 0x%x", pSrc->target);
748 return VERR_INVALID_PARAMETER;
749 }
750 }
751
752 Assert(pSrc->hwid);
753
754 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
755
756 if (cRects == 1)
757 {
758 /* just optimization to draw a single rect with GL_TRIANGLE_FAN */
759 GLfloat *pVerticies;
760 GLfloat *pTexCoords;
761 GLuint cElements = crBltVtGetNumVerticiesTF(cRects);
762
763 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
764 pTexCoords = crBltVtRectsTFNormalized(paDstRect, cRects, 1, 1, pVerticies, dstHeight);
765 crBltVtRectsTFNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, srcHeight);
766
767 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
768 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies CRVBOX_HOST_ONLY_PARAM(1 /*fRealPtr*/));
769
770 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
771 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords CRVBOX_HOST_ONLY_PARAM(1 /*fRealPtr*/));
772
773 pBlitter->pDispatch->Enable(pSrc->target);
774
775 pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
776
777 pBlitter->pDispatch->Disable(pSrc->target);
778
779 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
780 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
781 }
782 else
783 {
784 GLfloat *pVerticies;
785 GLfloat *pTexCoords;
786 GLubyte *pIndicies;
787 GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
788 GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
789 GLubyte iIdxBase = 0;
790
791 pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
792 pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
793 crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
794
795 pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
796 pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies CRVBOX_HOST_ONLY_PARAM(1 /*fRealPtr*/));
797
798 pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
799 pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords CRVBOX_HOST_ONLY_PARAM(1 /*fRealPtr*/));
800
801 pBlitter->pDispatch->Enable(pSrc->target);
802
803 pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
804
805 pBlitter->pDispatch->Disable(pSrc->target);
806
807 pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
808 pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
809 }
810
811 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
812
813 return VINF_SUCCESS;
814}
815
816static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
817{
818 const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
819 if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
820 {
821 pBlitter->Flags.SupportsFBO = 1;
822 pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
823 Assert(pBlitter->idFBO);
824 }
825 else
826 crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
827
828 if (crStrstr(pszExtension, "GL_ARB_pixel_buffer_object"))
829 pBlitter->Flags.SupportsPBO = 1;
830 else
831 crWarning("GL_ARB_pixel_buffer_object not supported");
832
833 /* BlitFramebuffer seems to be buggy on Intel,
834 * try always glDrawXxx for now */
835 if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
836 {
837 pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
838 }
839 else
840 {
841// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
842 pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
843 }
844
845 /* defaults. but just in case */
846 pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
847 pBlitter->pDispatch->LoadIdentity();
848 pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
849 pBlitter->pDispatch->LoadIdentity();
850
851 return VINF_SUCCESS;
852}
853
854#endif /* !IN_VMSVGA3D */
855
856
857void CrBltLeave(PCR_BLITTER pBlitter)
858{
859 if (!pBlitter->cEnters)
860 {
861 WARN(("blitter not entered!"));
862 return;
863 }
864
865 if (--pBlitter->cEnters)
866 return;
867
868#ifdef IN_VMSVGA3D
869 /** @todo IN_VMSVGA3D */
870#else
871 if (pBlitter->Flags.SupportsFBO)
872 {
873 pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
874 pBlitter->pDispatch->DrawBuffer(GL_BACK);
875 pBlitter->pDispatch->ReadBuffer(GL_BACK);
876 }
877
878 pBlitter->pDispatch->Flush();
879
880 if (pBlitter->CtxInfo.Base.id)
881 pBlitter->pDispatch->MakeCurrent(0, 0, 0);
882#endif
883}
884
885int CrBltEnter(PCR_BLITTER pBlitter)
886{
887 if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
888 {
889 WARN(("current mural not initialized!"));
890 return VERR_INVALID_STATE;
891 }
892
893 if (pBlitter->cEnters++)
894 return VINF_SUCCESS;
895
896 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)*/
897 {
898#ifdef IN_VMSVGA3D
899 /** @todo IN_VMSVGA3D */
900#else
901 pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
902#endif
903 }
904
905 if (pBlitter->Flags.Initialized)
906 return VINF_SUCCESS;
907
908#ifdef IN_VMSVGA3D
909 /** @todo IN_VMSVGA3D */
910 int rc = VINF_SUCCESS;
911#else
912 int rc = crBltInitOnMakeCurent(pBlitter);
913#endif
914 if (RT_SUCCESS(rc))
915 {
916 pBlitter->Flags.Initialized = 1;
917 return VINF_SUCCESS;
918 }
919
920 WARN(("crBltInitOnMakeCurent failed, rc %d", rc));
921 CrBltLeave(pBlitter);
922 return rc;
923}
924
925
926static 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)
927{
928#ifdef IN_VMSVGA3D
929 /** @todo IN_VMSVGA3D */
930#else
931 pBlitter->pDispatch->DrawBuffer(enmDstBuff);
932
933 crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
934
935 if (!(fFlags & CRBLT_F_NOALPHA))
936 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
937 else
938 {
939 int rc = pBlitter->Flags.ShadersGloal
940 ? CrGlslProgUseNoAlpha(pBlitter->pGlslCache, pSrc->target)
941 : CrGlslProgUseGenNoAlpha(&pBlitter->LocalGlslCache, pSrc->target);
942
943 if (!RT_SUCCESS(rc))
944 {
945 crWarning("Failed to use no-alpha program rc %d!, falling back to default blit", rc);
946 pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
947 return;
948 }
949
950 /* since we use shaders, we need to use draw commands rather than framebuffer blits.
951 * force using draw-based blitting */
952 crBltBlitTexBufImplDraw2D(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
953
954 Assert(pBlitter->Flags.ShadersGloal || &pBlitter->LocalGlslCache == pBlitter->pGlslCache);
955
956 CrGlslProgClear(pBlitter->pGlslCache);
957 }
958#endif
959}
960
961void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
962{
963 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
964 crBltCheckSetupViewport(pBlitter, &DstSize, false);
965}
966
967void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
968{
969 if (!CrBltIsEntered(pBlitter))
970 {
971 WARN(("CrBltBlitTexMural: blitter not entered"));
972 return;
973 }
974
975 RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
976
977#ifdef IN_VMSVGA3D
978 /** @todo IN_VMSVGA3D */
979#else
980 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
981#endif
982
983 crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
984}
985
986
987#ifndef IN_VMSVGA3D
988
989void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
990{
991 if (!CrBltIsEntered(pBlitter))
992 {
993 WARN(("CrBltBlitTexTex: blitter not entered"));
994 return;
995 }
996
997 RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
998
999 pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
1000
1001 /** @todo mag/min filters ? */
1002
1003 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
1004
1005// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1006// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1007
1008 crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
1009
1010 pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
1011}
1012
1013void CrBltPresent(PCR_BLITTER pBlitter)
1014{
1015 if (!CrBltIsEntered(pBlitter))
1016 {
1017 WARN(("CrBltPresent: blitter not entered"));
1018 return;
1019 }
1020
1021 if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
1022 pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
1023 else
1024 pBlitter->pDispatch->Flush();
1025}
1026
1027static int crBltImgInitBaseForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
1028{
1029 memset(pDst, 0, sizeof (*pDst));
1030 if (enmFormat != GL_RGBA
1031 && enmFormat != GL_BGRA)
1032 {
1033 WARN(("unsupported format 0x%x", enmFormat));
1034 return VERR_NOT_IMPLEMENTED;
1035 }
1036
1037 uint32_t bpp = 32;
1038
1039 uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
1040 uint32_t cbData = pitch * pSrc->height;
1041 pDst->cbData = cbData;
1042 pDst->enmFormat = enmFormat;
1043 pDst->width = pSrc->width;
1044 pDst->height = pSrc->height;
1045 pDst->bpp = bpp;
1046 pDst->pitch = pitch;
1047 return VINF_SUCCESS;
1048}
1049
1050static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
1051{
1052 int rc = crBltImgInitBaseForTex(pSrc, pDst, enmFormat);
1053 if (!RT_SUCCESS(rc))
1054 {
1055 crWarning("crBltImgInitBaseForTex failed rc %d", rc);
1056 return rc;
1057 }
1058
1059 uint32_t cbData = pDst->cbData;
1060 pDst->pvData = RTMemAllocZ(cbData);
1061 if (!pDst->pvData)
1062 {
1063 crWarning("RTMemAlloc failed");
1064 return VERR_NO_MEMORY;
1065 }
1066
1067#ifdef DEBUG_misha
1068 {
1069 char *pTmp = (char*)pDst->pvData;
1070 for (uint32_t i = 0; i < cbData; ++i)
1071 {
1072 pTmp[i] = (char)((1 << i) % 255);
1073 }
1074 }
1075#endif
1076 return VINF_SUCCESS;
1077}
1078
1079VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
1080{
1081 if (!CrBltIsEntered(pBlitter))
1082 {
1083 WARN(("CrBltImgGetTex: blitter not entered"));
1084 return VERR_INVALID_STATE;
1085 }
1086
1087 int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
1088 if (!RT_SUCCESS(rc))
1089 {
1090 crWarning("crBltImgCreateForTex failed, rc %d", rc);
1091 return rc;
1092 }
1093 pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
1094
1095#ifdef DEBUG_misha
1096 {
1097 GLint width = 0, height = 0, depth = 0;
1098 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
1099 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
1100 pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
1101
1102 Assert(width == pSrc->width);
1103 Assert(height == pSrc->height);
1104// Assert(depth == pSrc->depth);
1105 }
1106#endif
1107
1108 pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
1109
1110 pBlitter->pDispatch->BindTexture(pSrc->target, 0);
1111 return VINF_SUCCESS;
1112}
1113
1114VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
1115{
1116 (void)fBb; (void)pDst;
1117 if (!CrBltIsEntered(pBlitter))
1118 {
1119 WARN(("CrBltImgGetMural: blitter not entered"));
1120 return VERR_INVALID_STATE;
1121 }
1122
1123 WARN(("NOT IMPLEMENTED"));
1124 return VERR_NOT_IMPLEMENTED;
1125}
1126
1127VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
1128{
1129 if (!CrBltIsEntered(pBlitter))
1130 {
1131 WARN(("CrBltImgFree: blitter not entered"));
1132 return;
1133 }
1134
1135 if (pDst->pvData)
1136 {
1137 RTMemFree(pDst->pvData);
1138 pDst->pvData = NULL;
1139 }
1140}
1141
1142
1143VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache)
1144{
1145 if (pCache->iGlVersion == 0)
1146 {
1147 const char * pszStr = (const char*)pCache->pDispatch->GetString(GL_VERSION);
1148 pCache->iGlVersion = crStrParseGlVersion(pszStr);
1149 if (pCache->iGlVersion <= 0)
1150 {
1151 crWarning("crStrParseGlVersion returned %d", pCache->iGlVersion);
1152 pCache->iGlVersion = -1;
1153 }
1154 }
1155
1156 if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
1157 return true;
1158
1159 crWarning("GLSL unsuported, gl version %d", pCache->iGlVersion);
1160
1161 /** @todo we could also check for GL_ARB_shader_objects and GL_ARB_fragment_shader,
1162 * but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
1163 return false;
1164}
1165
1166#define CR_GLSL_STR_V_120 "#version 120\n"
1167#define CR_GLSL_STR_EXT_TR "#extension GL_ARB_texture_rectangle : enable\n"
1168#define CR_GLSL_STR_2D "2D"
1169#define CR_GLSL_STR_2DRECT "2DRect"
1170
1171#define CR_GLSL_PATTERN_FS_NOALPHA(_ver, _ext, _tex) \
1172 _ver \
1173 _ext \
1174 "uniform sampler" _tex " sampler0;\n" \
1175 "void main()\n" \
1176 "{\n" \
1177 "vec2 srcCoord = vec2(gl_TexCoord[0]);\n" \
1178 "gl_FragData[0].xyz = (texture" _tex "(sampler0, srcCoord).xyz);\n" \
1179 "gl_FragData[0].w = 1.0;\n" \
1180 "}\n"
1181
1182static const char* crGlslGetFsStringNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1183{
1184 if (!CrGlslIsSupported(pCache))
1185 {
1186 crWarning("CrGlslIsSupported is false");
1187 return NULL;
1188 }
1189
1190 if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 1, 0))
1191 {
1192 if (enmTexTarget == GL_TEXTURE_2D)
1193 return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, "", CR_GLSL_STR_2D);
1194 else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
1195 return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
1196
1197 crWarning("invalid enmTexTarget %#x", enmTexTarget);
1198 return NULL;
1199 }
1200 else if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
1201 {
1202 if (enmTexTarget == GL_TEXTURE_2D)
1203 return CR_GLSL_PATTERN_FS_NOALPHA("", "", CR_GLSL_STR_2D);
1204 else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
1205 return CR_GLSL_PATTERN_FS_NOALPHA("", CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
1206
1207 crWarning("invalid enmTexTarget %#x", enmTexTarget);
1208 return NULL;
1209 }
1210
1211 crError("crGlslGetFsStringNoAlpha: we should not be here!");
1212 return NULL;
1213}
1214
1215static int crGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget, GLuint *puiProgram)
1216{
1217 *puiProgram = 0;
1218
1219 const char*pStrFsShader = crGlslGetFsStringNoAlpha(pCache, enmTexTarget);
1220 if (!pStrFsShader)
1221 {
1222 crWarning("crGlslGetFsStringNoAlpha failed");
1223 return VERR_NOT_SUPPORTED;
1224 }
1225
1226 int rc = VINF_SUCCESS;
1227 GLchar * pBuf = NULL;
1228 GLuint uiProgram = 0;
1229 GLint iUniform = -1;
1230 GLuint uiShader = pCache->pDispatch->CreateShader(GL_FRAGMENT_SHADER);
1231 if (!uiShader)
1232 {
1233 crWarning("CreateShader failed");
1234 return VERR_NOT_SUPPORTED;
1235 }
1236
1237 pCache->pDispatch->ShaderSource(uiShader, 1, &pStrFsShader, NULL);
1238
1239 pCache->pDispatch->CompileShader(uiShader);
1240
1241 GLint compiled = 0;
1242 pCache->pDispatch->GetShaderiv(uiShader, GL_COMPILE_STATUS, &compiled);
1243
1244#ifndef DEBUG_misha
1245 if(!compiled)
1246#endif
1247 {
1248 if (!pBuf)
1249 pBuf = (GLchar *)RTMemAlloc(16300);
1250 pCache->pDispatch->GetShaderInfoLog(uiShader, 16300, NULL, pBuf);
1251#ifdef DEBUG_misha
1252 if (compiled)
1253 crDebug("compile success:\n-------------------\n%s\n--------\n", pBuf);
1254 else
1255#endif
1256 {
1257 crWarning("compile FAILURE:\n-------------------\n%s\n--------\n", pBuf);
1258 rc = VERR_NOT_SUPPORTED;
1259 goto end;
1260 }
1261 }
1262
1263 Assert(compiled);
1264
1265 uiProgram = pCache->pDispatch->CreateProgram();
1266 if (!uiProgram)
1267 {
1268 rc = VERR_NOT_SUPPORTED;
1269 goto end;
1270 }
1271
1272 pCache->pDispatch->AttachShader(uiProgram, uiShader);
1273
1274 pCache->pDispatch->LinkProgram(uiProgram);
1275
1276 GLint linked;
1277 pCache->pDispatch->GetProgramiv(uiProgram, GL_LINK_STATUS, &linked);
1278#ifndef DEBUG_misha
1279 if(!linked)
1280#endif
1281 {
1282 if (!pBuf)
1283 pBuf = (GLchar *)RTMemAlloc(16300);
1284 pCache->pDispatch->GetProgramInfoLog(uiProgram, 16300, NULL, pBuf);
1285#ifdef DEBUG_misha
1286 if (linked)
1287 crDebug("link success:\n-------------------\n%s\n--------\n", pBuf);
1288 else
1289#endif
1290 {
1291 crWarning("link FAILURE:\n-------------------\n%s\n--------\n", pBuf);
1292 rc = VERR_NOT_SUPPORTED;
1293 goto end;
1294 }
1295 }
1296
1297 Assert(linked);
1298
1299 iUniform = pCache->pDispatch->GetUniformLocation(uiProgram, "sampler0");
1300 if (iUniform == -1)
1301 {
1302 crWarning("GetUniformLocation failed for sampler0");
1303 }
1304 else
1305 {
1306 pCache->pDispatch->Uniform1i(iUniform, 0);
1307 }
1308
1309 *puiProgram = uiProgram;
1310
1311 /* avoid end finalizer from cleaning it */
1312 uiProgram = 0;
1313
1314 end:
1315 if (uiShader)
1316 pCache->pDispatch->DeleteShader(uiShader);
1317 if (uiProgram)
1318 pCache->pDispatch->DeleteProgram(uiProgram);
1319 if (pBuf)
1320 RTMemFree(pBuf);
1321 return rc;
1322}
1323
1324DECLINLINE(GLuint) crGlslProgGetNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1325{
1326 switch (enmTexTarget)
1327 {
1328 case GL_TEXTURE_2D:
1329 return pCache->uNoAlpha2DProg;
1330 case GL_TEXTURE_RECTANGLE_ARB:
1331 return pCache->uNoAlpha2DRectProg;
1332 default:
1333 crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
1334 return 0;
1335 }
1336}
1337
1338DECLINLINE(GLuint*) crGlslProgGetNoAlphaPtr(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1339{
1340 switch (enmTexTarget)
1341 {
1342 case GL_TEXTURE_2D:
1343 return &pCache->uNoAlpha2DProg;
1344 case GL_TEXTURE_RECTANGLE_ARB:
1345 return &pCache->uNoAlpha2DRectProg;
1346 default:
1347 crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
1348 return NULL;
1349 }
1350}
1351
1352VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1353{
1354 GLuint*puiProgram = crGlslProgGetNoAlphaPtr(pCache, enmTexTarget);
1355 if (!puiProgram)
1356 return VERR_INVALID_PARAMETER;
1357
1358 if (*puiProgram)
1359 return VINF_SUCCESS;
1360
1361 return crGlslProgGenNoAlpha(pCache, enmTexTarget, puiProgram);
1362}
1363
1364VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache)
1365{
1366 int rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_2D);
1367 if (!RT_SUCCESS(rc))
1368 {
1369 crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_2D failed rc %d", rc);
1370 return rc;
1371 }
1372
1373 rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_RECTANGLE_ARB);
1374 if (!RT_SUCCESS(rc))
1375 {
1376 crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_RECTANGLE failed rc %d", rc);
1377 return rc;
1378 }
1379
1380 return VINF_SUCCESS;
1381}
1382
1383VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache)
1384{
1385 pCache->pDispatch->UseProgram(0);
1386}
1387
1388VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1389{
1390 GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
1391 if (!uiProg)
1392 {
1393 crWarning("request to use inexistent program!");
1394 return VERR_INVALID_STATE;
1395 }
1396
1397 Assert(uiProg);
1398
1399 pCache->pDispatch->UseProgram(uiProg);
1400
1401 return VINF_SUCCESS;
1402}
1403
1404VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
1405{
1406 GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
1407 if (!uiProg)
1408 {
1409 int rc = CrGlslProgGenNoAlpha(pCache, enmTexTarget);
1410 if (!RT_SUCCESS(rc))
1411 {
1412 crWarning("CrGlslProgGenNoAlpha failed, rc %d", rc);
1413 return rc;
1414 }
1415
1416 uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
1417 CRASSERT(uiProg);
1418 }
1419
1420 Assert(uiProg);
1421
1422 pCache->pDispatch->UseProgram(uiProg);
1423
1424 return VINF_SUCCESS;
1425}
1426
1427#endif /* !IN_VMSVGA3D */
1428
1429VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache)
1430{
1431 return pCache->uNoAlpha2DProg || pCache->uNoAlpha2DRectProg;
1432}
1433
1434VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache)
1435{
1436 if (pCache->uNoAlpha2DProg)
1437 {
1438#ifdef IN_VMSVGA3D
1439 /** @todo IN_VMSVGA3D */
1440#else
1441 pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DProg);
1442#endif
1443 pCache->uNoAlpha2DProg = 0;
1444 }
1445
1446 if (pCache->uNoAlpha2DRectProg)
1447 {
1448#ifdef IN_VMSVGA3D
1449 /** @todo IN_VMSVGA3D */
1450#else
1451 pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DRectProg);
1452#endif
1453 pCache->uNoAlpha2DRectProg = 0;
1454 }
1455}
1456
1457VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache)
1458{
1459 CRASSERT(!CrGlslNeedsCleanup(pCache));
1460
1461 CrGlslCleanup(pCache);
1462
1463 /* sanity */
1464 memset(pCache, 0, sizeof (*pCache));
1465}
1466
1467#ifndef IN_VMSVGA3D
1468
1469/*TdBlt*/
1470static void crTdBltCheckPBO(PCR_TEXDATA pTex)
1471{
1472 if (pTex->idPBO)
1473 return;
1474
1475 PCR_BLITTER pBlitter = pTex->pBlitter;
1476
1477 if (!pBlitter->Flags.SupportsPBO)
1478 return;
1479
1480 pBlitter->pDispatch->GenBuffersARB(1, &pTex->idPBO);
1481 if (!pTex->idPBO)
1482 {
1483 crWarning("PBO create failed");
1484 return;
1485 }
1486
1487 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
1488 pBlitter->pDispatch->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
1489 pTex->Tex.width*pTex->Tex.height*4,
1490 0, GL_STREAM_READ_ARB);
1491 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1492}
1493
1494static uint32_t crTdBltTexCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget)
1495{
1496 uint32_t tex = 0;
1497 pBlitter->pDispatch->GenTextures(1, &tex);
1498 if (!tex)
1499 {
1500 crWarning("Tex create failed");
1501 return 0;
1502 }
1503
1504 pBlitter->pDispatch->BindTexture(enmTarget, tex);
1505 pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1506 pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1507 pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
1508 pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
1509 pBlitter->pDispatch->TexImage2D(enmTarget, 0, GL_RGBA8,
1510 width, height,
1511 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
1512
1513
1514 /*Restore gl state*/
1515 pBlitter->pDispatch->BindTexture(enmTarget, 0);
1516
1517 return tex;
1518}
1519
1520int crTdBltCheckInvertTex(PCR_TEXDATA pTex)
1521{
1522 if (pTex->idInvertTex)
1523 return VINF_SUCCESS;
1524
1525 pTex->idInvertTex = crTdBltTexCreate(pTex->pBlitter, pTex->Tex.width, pTex->Tex.height, pTex->Tex.target);
1526 if (!pTex->idInvertTex)
1527 {
1528 crWarning("Invert Tex create failed");
1529 return VERR_GENERAL_FAILURE;
1530 }
1531 return VINF_SUCCESS;
1532}
1533
1534#endif /* !IN_VMSVGA3D */
1535
1536
1537void crTdBltImgRelease(PCR_TEXDATA pTex)
1538{
1539 pTex->Flags.DataValid = 0;
1540}
1541
1542void crTdBltImgFree(PCR_TEXDATA pTex)
1543{
1544 if (!pTex->Img.pvData)
1545 {
1546 Assert(!pTex->Flags.DataValid);
1547 return;
1548 }
1549
1550 crTdBltImgRelease(pTex);
1551
1552 Assert(!pTex->Flags.DataValid);
1553
1554
1555 if (pTex->idPBO)
1556 {
1557 PCR_BLITTER pBlitter = pTex->pBlitter;
1558
1559 Assert(CrBltIsEntered(pBlitter));
1560#ifdef IN_VMSVGA3D
1561 /** @todo IN_VMSVGA3D */
1562#else
1563 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
1564 pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1565 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1566#endif
1567 }
1568 else
1569 {
1570 Assert(pTex->Img.pvData);
1571 RTMemFree(pTex->Img.pvData);
1572 }
1573
1574 pTex->Img.pvData = NULL;
1575}
1576
1577
1578#ifndef IN_VMSVGA3D
1579
1580int crTdBltImgAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted)
1581{
1582 void *pvData = pTex->Img.pvData;
1583 Assert(!pTex->Flags.DataValid);
1584 int rc = crBltImgInitBaseForTex(&pTex->Tex, &pTex->Img, enmFormat);
1585 if (!RT_SUCCESS(rc))
1586 {
1587 WARN(("crBltImgInitBaseForTex failed rc %d", rc));
1588 return rc;
1589 }
1590
1591 PCR_BLITTER pBlitter = pTex->pBlitter;
1592 Assert(CrBltIsEntered(pBlitter));
1593 pBlitter->pDispatch->BindTexture(pTex->Tex.target, fInverted ? pTex->idInvertTex : pTex->Tex.hwid);
1594
1595 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
1596
1597 if (pvData)
1598 {
1599 if (pTex->idPBO)
1600 {
1601 pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1602 pvData = NULL;
1603
1604 }
1605 }
1606 else
1607 {
1608 if (!pTex->idPBO)
1609 {
1610 pvData = RTMemAlloc(4*pTex->Tex.width*pTex->Tex.height);
1611 if (!pvData)
1612 {
1613 WARN(("Out of memory in crTdBltImgAcquire"));
1614 pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
1615 return VERR_NO_MEMORY;
1616 }
1617 }
1618 }
1619
1620 Assert(!pvData == !!pTex->idPBO);
1621
1622 /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
1623 pBlitter->pDispatch->GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
1624
1625 /*restore gl state*/
1626 pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
1627
1628 if (pTex->idPBO)
1629 {
1630 pvData = pBlitter->pDispatch->MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1631 if (!pvData)
1632 {
1633 WARN(("Failed to MapBuffer in CrHlpGetTexImage"));
1634 return VERR_GENERAL_FAILURE;
1635 }
1636
1637 pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1638 }
1639
1640 Assert(pvData);
1641 pTex->Img.pvData = pvData;
1642 pTex->Flags.DataValid = 1;
1643 pTex->Flags.DataInverted = fInverted;
1644 return VINF_SUCCESS;
1645}
1646
1647#endif /* !IN_VMSVGA3D */
1648
1649
1650/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataInvalidateNe or CrTdBltDataCleanup */
1651VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex)
1652{
1653 if (!pTex->Flags.Entered)
1654 {
1655 WARN(("tex not entered"));
1656 return VERR_INVALID_STATE;
1657 }
1658
1659 if (!pTex->Flags.DataAcquired)
1660 {
1661 WARN(("Data NOT acquired"));
1662 return VERR_INVALID_STATE;
1663 }
1664
1665 Assert(pTex->Img.pvData);
1666 Assert(pTex->Flags.DataValid);
1667
1668 pTex->Flags.DataAcquired = 0;
1669
1670 return VINF_SUCCESS;
1671}
1672
1673static void crTdBltDataFree(PCR_TEXDATA pTex)
1674{
1675 crTdBltImgFree(pTex);
1676
1677 if (pTex->pScaledCache)
1678 CrTdBltDataFreeNe(pTex->pScaledCache);
1679}
1680
1681/* discard the texture data cached with previous CrTdBltDataAcquire.
1682 * Must be called wit data released (CrTdBltDataRelease) */
1683VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex)
1684{
1685 if (!pTex->Flags.Entered)
1686 {
1687 WARN(("tex not entered"));
1688 return VERR_INVALID_STATE;
1689 }
1690
1691 crTdBltDataFree(pTex);
1692
1693 return VINF_SUCCESS;
1694}
1695
1696VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex)
1697{
1698 crTdBltImgRelease(pTex);
1699
1700 if (pTex->pScaledCache)
1701 CrTdBltDataInvalidateNe(pTex->pScaledCache);
1702}
1703
1704VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex)
1705{
1706 if (!pTex->Img.pvData)
1707 return VINF_SUCCESS;
1708
1709 bool fEntered = false;
1710 if (pTex->idPBO)
1711 {
1712 int rc = CrTdBltEnter(pTex);
1713 if (!RT_SUCCESS(rc))
1714 {
1715 WARN(("err"));
1716 return rc;
1717 }
1718
1719 fEntered = true;
1720 }
1721
1722 crTdBltDataFree(pTex);
1723
1724 if (fEntered)
1725 CrTdBltLeave(pTex);
1726
1727 return VINF_SUCCESS;
1728}
1729
1730static void crTdBltSdCleanupCacheNe(PCR_TEXDATA pTex)
1731{
1732 if (pTex->pScaledCache)
1733 {
1734 CrTdBltDataCleanupNe(pTex->pScaledCache);
1735 CrTdRelease(pTex->pScaledCache);
1736 pTex->pScaledCache = NULL;
1737 }
1738}
1739
1740static void crTdBltDataCleanup(PCR_TEXDATA pTex)
1741{
1742 crTdBltImgFree(pTex);
1743
1744 PCR_BLITTER pBlitter = pTex->pBlitter;
1745
1746 if (pTex->idPBO)
1747 {
1748 Assert(CrBltIsEntered(pBlitter));
1749#ifdef IN_VMSVGA3D
1750 /** @todo IN_VMSVGA3D */
1751#else
1752 pBlitter->pDispatch->DeleteBuffersARB(1, &pTex->idPBO);
1753#endif
1754 pTex->idPBO = 0;
1755 }
1756
1757 if (pTex->idInvertTex)
1758 {
1759 Assert(CrBltIsEntered(pBlitter));
1760#ifdef IN_VMSVGA3D
1761 /** @todo IN_VMSVGA3D */
1762#else
1763 pBlitter->pDispatch->DeleteTextures(1, &pTex->idInvertTex);
1764#endif
1765 pTex->idInvertTex = 0;
1766 }
1767
1768 crTdBltSdCleanupCacheNe(pTex);
1769}
1770
1771/* does same as CrTdBltDataFree, and in addition cleans up */
1772VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex)
1773{
1774 if (!pTex->Flags.Entered)
1775 {
1776 WARN(("tex not entered"));
1777 return VERR_INVALID_STATE;
1778 }
1779
1780 crTdBltDataCleanup(pTex);
1781
1782 return VINF_SUCCESS;
1783}
1784
1785VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex)
1786{
1787 bool fEntered = false;
1788 if (pTex->idPBO || pTex->idInvertTex)
1789 {
1790 int rc = CrTdBltEnter(pTex);
1791 if (!RT_SUCCESS(rc))
1792 {
1793 WARN(("err"));
1794 return rc;
1795 }
1796
1797 fEntered = true;
1798 }
1799
1800 crTdBltDataCleanup(pTex);
1801
1802 if (fEntered)
1803 CrTdBltLeave(pTex);
1804
1805 return VINF_SUCCESS;
1806}
1807
1808
1809#ifndef IN_VMSVGA3D
1810
1811/* acquire the texture data, returns the cached data in case it is cached.
1812 * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup.
1813 * */
1814VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg)
1815{
1816 if (!pTex->Flags.Entered)
1817 {
1818 WARN(("tex not entered"));
1819 return VERR_INVALID_STATE;
1820 }
1821
1822 if (pTex->Flags.DataAcquired)
1823 {
1824 WARN(("Data acquired already"));
1825 return VERR_INVALID_STATE;
1826 }
1827
1828 if (pTex->Flags.DataValid && pTex->Img.enmFormat == enmFormat && !pTex->Flags.DataInverted == !fInverted)
1829 {
1830 Assert(pTex->Img.pvData);
1831 *ppImg = &pTex->Img;
1832 pTex->Flags.DataAcquired = 1;
1833 return VINF_SUCCESS;
1834 }
1835
1836 crTdBltImgRelease(pTex);
1837
1838 crTdBltCheckPBO(pTex);
1839
1840 int rc;
1841
1842 if (fInverted)
1843 {
1844 rc = crTdBltCheckInvertTex(pTex);
1845 if (!RT_SUCCESS(rc))
1846 {
1847 WARN(("crTdBltCheckInvertTex failed rc %d", rc));
1848 return rc;
1849 }
1850
1851 RTRECT SrcRect, DstRect;
1852 VBOXVR_TEXTURE InvertTex;
1853
1854 InvertTex = pTex->Tex;
1855 InvertTex.hwid = pTex->idInvertTex;
1856
1857 SrcRect.xLeft = 0;
1858 SrcRect.yTop = InvertTex.height;
1859 SrcRect.xRight = InvertTex.width;
1860 SrcRect.yBottom = 0;
1861
1862 DstRect.xLeft = 0;
1863 DstRect.yTop = 0;
1864 DstRect.xRight = InvertTex.width;
1865 DstRect.yBottom = InvertTex.height;
1866
1867 CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &InvertTex, &DstRect, 1, 0);
1868 }
1869
1870 rc = crTdBltImgAcquire(pTex, enmFormat, fInverted);
1871 if (!RT_SUCCESS(rc))
1872 {
1873 WARN(("crTdBltImgAcquire failed rc %d", rc));
1874 return rc;
1875 }
1876
1877 Assert(pTex->Img.pvData);
1878 *ppImg = &pTex->Img;
1879 pTex->Flags.DataAcquired = 1;
1880
1881 return VINF_SUCCESS;
1882}
1883
1884DECLINLINE(void) crTdResize(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex)
1885{
1886 crTdBltDataCleanup(pTex);
1887
1888 pTex->Tex = *pVrTex;
1889}
1890
1891static DECLCALLBACK(void) ctTdBltSdReleased(struct CR_TEXDATA *pTexture)
1892{
1893 PCR_BLITTER pBlitter = pTexture->pBlitter;
1894
1895 int rc = CrBltEnter(pBlitter);
1896 if (!RT_SUCCESS(rc))
1897 {
1898 WARN(("CrBltEnter failed, rc %d", rc));
1899 return;
1900 }
1901
1902 CrTdBltDataCleanupNe(pTexture);
1903
1904 pBlitter->pDispatch->DeleteTextures(1, &pTexture->Tex.hwid);
1905
1906 CrBltLeave(pBlitter);
1907
1908 RTMemFree(pTexture);
1909}
1910
1911static int ctTdBltSdCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget, PCR_TEXDATA *ppScaledCache)
1912{
1913 PCR_TEXDATA pScaledCache;
1914
1915 Assert(CrBltIsEntered(pBlitter));
1916
1917 *ppScaledCache = NULL;
1918
1919 pScaledCache = (PCR_TEXDATA)RTMemAlloc(sizeof (*pScaledCache));
1920 if (!pScaledCache)
1921 {
1922 WARN(("RTMemAlloc failed"));
1923 return VERR_NO_MEMORY;
1924 }
1925
1926 VBOXVR_TEXTURE Tex;
1927 Tex.width = width;
1928 Tex.height = height;
1929 Tex.target = enmTarget;
1930 Tex.hwid = crTdBltTexCreate(pBlitter, width, height, enmTarget);
1931 if (!Tex.hwid)
1932 {
1933 WARN(("Tex create failed"));
1934 RTMemFree(pScaledCache);
1935 return VERR_GENERAL_FAILURE;
1936 }
1937
1938 CrTdInit(pScaledCache, &Tex, pBlitter, ctTdBltSdReleased);
1939
1940 *ppScaledCache = pScaledCache;
1941
1942 return VINF_SUCCESS;
1943}
1944
1945static int ctTdBltSdGet(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
1946{
1947 Assert(CrBltIsEntered(pTex->pBlitter));
1948
1949 PCR_TEXDATA pScaledCache;
1950
1951 *ppScaledCache = NULL;
1952
1953 if (!pTex->pScaledCache)
1954 {
1955 int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
1956 if (!RT_SUCCESS(rc))
1957 {
1958 WARN(("ctTdBltSdCreate failed %d", rc));
1959 return rc;
1960 }
1961
1962 pTex->pScaledCache = pScaledCache;
1963 }
1964 else
1965 {
1966 int cmp = pTex->pScaledCache->Tex.width - width;
1967 if (cmp <= 0)
1968 cmp = pTex->pScaledCache->Tex.height - height;
1969
1970 if (!cmp)
1971 pScaledCache = pTex->pScaledCache;
1972 else if (cmp < 0) /* current cache is "less" than the requested */
1973 {
1974 int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
1975 if (!RT_SUCCESS(rc))
1976 {
1977 WARN(("ctTdBltSdCreate failed %d", rc));
1978 return rc;
1979 }
1980
1981 pScaledCache->pScaledCache = pTex->pScaledCache;
1982 pTex->pScaledCache = pScaledCache;
1983 }
1984 else /* cmp > 0 */
1985 {
1986 int rc = ctTdBltSdGet(pTex->pScaledCache, width, height, &pScaledCache);
1987 if (!RT_SUCCESS(rc))
1988 {
1989 WARN(("ctTdBltSdGet failed %d", rc));
1990 return rc;
1991 }
1992 }
1993 }
1994
1995 Assert(pScaledCache);
1996
1997#if 0
1998 {
1999 VBOXVR_TEXTURE Tex;
2000 Tex.width = width;
2001 Tex.height = height;
2002 Tex.target = pTex->Tex.target;
2003 Tex.hwid = crTdBltTexCreate(pTex, width, height);
2004 if (!Tex.hwid)
2005 {
2006 WARN(("Tex create failed"));
2007 return VERR_GENERAL_FAILURE;
2008 }
2009
2010 pTex->pBlitter->pDispatch->DeleteTextures(1, &pTex->pScaledCache->Tex.hwid);
2011
2012 crTdResize(pTex->pScaledCache, &Tex);
2013 }
2014#endif
2015
2016 *ppScaledCache = pScaledCache;
2017 return VINF_SUCCESS;
2018}
2019
2020static int ctTdBltSdGetUpdated(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
2021{
2022 PCR_TEXDATA pScaledCache;
2023
2024 *ppScaledCache = NULL;
2025 int rc = ctTdBltSdGet(pTex, width, height, &pScaledCache);
2026 if (!RT_SUCCESS(rc))
2027 {
2028 WARN(("ctTdBltSdGet failed %d", rc));
2029 return rc;
2030 }
2031
2032 Assert(width == (uint32_t)pScaledCache->Tex.width);
2033 Assert(height == (uint32_t)pScaledCache->Tex.height);
2034
2035 if (!pScaledCache->Flags.DataValid)
2036 {
2037 RTRECT SrcRect, DstRect;
2038
2039 SrcRect.xLeft = 0;
2040 SrcRect.yTop = 0;
2041 SrcRect.xRight = pTex->Tex.width;
2042 SrcRect.yBottom = pTex->Tex.height;
2043
2044 DstRect.xLeft = 0;
2045 DstRect.yTop = 0;
2046 DstRect.xRight = width;
2047 DstRect.yBottom = height;
2048
2049 CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &pScaledCache->Tex, &DstRect, 1, 0);
2050 }
2051
2052 *ppScaledCache = pScaledCache;
2053
2054 return VINF_SUCCESS;
2055}
2056
2057VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg)
2058{
2059 if ((uint32_t)pTex->Tex.width == width && (uint32_t)pTex->Tex.height == height)
2060 return CrTdBltDataAcquire(pTex, enmFormat, fInverted, ppImg);
2061
2062 if (!pTex->Flags.Entered)
2063 {
2064 WARN(("tex not entered"));
2065 return VERR_INVALID_STATE;
2066 }
2067
2068 PCR_TEXDATA pScaledCache;
2069
2070 int rc = ctTdBltSdGetUpdated(pTex, width, height, &pScaledCache);
2071 if (!RT_SUCCESS(rc))
2072 {
2073 WARN(("ctTdBltSdGetUpdated failed rc %d", rc));
2074 return rc;
2075 }
2076
2077 rc = CrTdBltEnter(pScaledCache);
2078 if (!RT_SUCCESS(rc))
2079 {
2080 WARN(("CrTdBltEnter failed rc %d", rc));
2081 return rc;
2082 }
2083
2084 rc = CrTdBltDataAcquire(pScaledCache, enmFormat, fInverted, ppImg);
2085 if (!RT_SUCCESS(rc))
2086 {
2087 WARN(("CrTdBltDataAcquire failed rc %d", rc));
2088 CrTdBltLeave(pTex->pScaledCache);
2089 return rc;
2090 }
2091
2092 return VINF_SUCCESS;
2093}
2094
2095VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg)
2096{
2097 PCR_TEXDATA pScaledCache = RT_FROM_MEMBER(pImg, CR_TEXDATA, Img);
2098 int rc = CrTdBltDataRelease(pScaledCache);
2099 if (!RT_SUCCESS(rc))
2100 {
2101 WARN(("CrTdBltDataRelease failed rc %d", rc));
2102 return rc;
2103 }
2104
2105 if (pScaledCache != pTex)
2106 CrTdBltLeave(pScaledCache);
2107
2108 return VINF_SUCCESS;
2109}
2110
2111VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex)
2112{
2113 if (!pTex->pScaledCache)
2114 return;
2115
2116 crTdBltSdCleanupCacheNe(pDstTex);
2117
2118 pDstTex->pScaledCache = pTex->pScaledCache;
2119 pTex->pScaledCache = NULL;
2120}
2121
2122#endif /* !IN_VMSVGA3D */
2123
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