VirtualBox

Changeset 54210 in vbox for trunk/src/VBox/Devices/Graphics


Ignore:
Timestamp:
Feb 15, 2015 3:58:41 AM (10 years ago)
Author:
vboxsync
Message:

DevVGA=SVGA3d-ogl.cpp: Don't crash should glMapBuffer return NULL, LogRel (assert in strict) the first few occurences.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp

    r54166 r54210  
    179179#endif
    180180
     181/** @def VMSVGA3D_CLEAR_LAST_ERRORS
     182 * Clears all pending OpenGL errors.
     183 *
     184 * If I understood this correctly, OpenGL maintains a bitmask internally and
     185 * glGetError gets the next bit (clearing it) from the bitmap and translates it
     186 * into a GL_XXX constant value which it then returns.  A single OpenGL call can
     187 * set more than one bit, and they stick around across calls, from what I
     188 * understand.
     189 *
     190 * So in order to be able to use glGetError to check whether a function
     191 * succeeded, we need to call glGetError until all error bits have been cleared.
     192 * This macro does that (in all types of builds).
     193 *
     194 * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS
     195 */
     196#define VMSVGA3D_CLEAR_GL_ERRORS() \
     197    do { \
     198        if (RT_UNLIKELY(glGetError() != GL_NO_ERROR)) /* predict no errors pending */ \
     199        { \
     200            uint32_t iErrorClearingLoopsLeft = 64; \
     201            while (glGetError() != GL_NO_ERROR && iErrorClearingLoopsLeft > 0) \
     202                iErrorClearingLoopsLeft--; \
     203        } \
     204    } while (0)
     205
     206/** @def VMSVGA3D_GET_LAST_GL_ERROR
     207 * Gets the last OpenGL error, stores it in a_pContext->lastError and returns
     208 * it.
     209 *
     210 * @returns Same as glGetError.
     211 * @param   a_pContext  The context to store the error in.
     212 *
     213 * @sa VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN
     214 */
     215#define VMSVGA3D_GET_GL_ERROR(a_pContext) ((a_pContext)->lastError = glGetError())
     216
     217/** @def VMSVGA3D_GL_SUCCESS
     218 * Checks whether VMSVGA3D_GET_LAST_GL_ERROR() return GL_NO_ERROR.
     219 *
     220 * Will call glGetError() and store the result in a_pContext->lastError.
     221 * Will predict GL_NO_ERROR outcome.
     222 *
     223 * @returns True on success, false on error.
     224 * @parm    a_pContext  The context to store the error in.
     225 *
     226 * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_COMPLAIN
     227 */
     228#define VMSVGA3D_GL_IS_SUCCESS(a_pContext) RT_LIKELY((((a_pContext)->lastError = glGetError()) == GL_NO_ERROR))
     229
     230/** @def VMSVGA3D_GL_COMPLAIN
     231 * Complains about one or more OpenGL errors (first in a_pContext->lastError).
     232 *
     233 * Strict builds will trigger an assertion, while other builds will put the
     234 * first few occurences in the release log.
     235 *
     236 * All GL errors will be cleared after invocation.  Assumes lastError
     237 * is an error, will not check for GL_NO_ERROR.
     238 *
     239 * @param   a_pState        The 3D state structure.
     240 * @param   a_pContext      The context that holds the first error.
     241 * @param   a_LogRelDetails Argument list for LogRel or similar that describes
     242 *                          the operation in greater detail.
     243 *
     244 * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS
     245 */
     246#ifdef VBOX_STRICT
     247# define VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \
     248    do { \
     249        AssertMsg((a_pState)->idActiveContext == (a_pContext)->id, \
     250                  ("idActiveContext=%#x id=%#x\n", (a_pState)->idActiveContext, (a_pContext)->id)); \
     251        RTAssertMsg2Weak a_LogRelDetails; \
     252        GLenum iNextError; \
     253        while ((iNextError = glGetError()) != GL_NO_ERROR) \
     254            RTAssertMsg2Weak("next error: %#x\n", iNextError); \
     255        AssertMsgFailed(("first error: %#x (idActiveContext=%#x)\n", (a_pContext)->lastError, (a_pContext)->id)); \
     256    } while (0)
     257#else
     258# define VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \
     259    do { \
     260        LogRelMax(32, ("VMSVGA3d: OpenGL error %#x (idActiveContext=%#x) on line %u ", (a_pContext)->lastError, (a_pContext)->id)); \
     261        GLenum iNextError; \
     262        while ((iNextError = glGetError()) != GL_NO_ERROR) \
     263            LogRelMax(32, (" - also error %#x ", iNextError)); \
     264        LogRelMax(32, a_LogRelDetails); \
     265    } while (0)
     266#endif
     267
     268/** @def VMSVGA3D_GL_GET_AND_COMPLAIN
     269 * Combination of VMSVGA3D_GET_GL_ERROR and VMSVGA3D_GL_COMPLAIN, assuming that
     270 * there is a pending error.
     271 *
     272 * @param   a_pState    The 3D state structure.
     273 * @param   a_pContext  The context that holds the first error.
     274 *
     275 * @sa VMSVGA3D_GET_GL_ERROR, VMSVGA3D_GL_IS_SUCCESS, VMSVGA3D_GL_COMPLAIN
     276 */
     277#define VMSVGA3D_GL_GET_AND_COMPLAIN(a_pState, a_pContext, a_LogRelDetails) \
     278    do { \
     279        VMSVGA3D_GET_GL_ERROR(a_pContext); \
     280        VMSVGA3D_GL_COMPLAIN(a_pState, a_pContext, a_LogRelDetails); \
     281    } while (0)
     282
     283
    181284/** @def VMSVGA3D_CHECK_LAST_ERROR
    182285 * Checks that the last OpenGL error code indicates success.
     
    186289 *
    187290 * @parm    pState      The VMSVGA3d state.
    188  * @parm    pContext    The new context.
     291 * @parm    pContext    The context.
    189292 *
    190  * @todo    Revamp this to include the OpenGL operation so we can see what went
    191  *          wrong.  Maybe include a few of the first occurances in the release
    192  *          log of regular builds.
     293 * @todo    Replace with proper error handling, it's crazy to return
     294 *          VERR_INTERNAL_ERROR in strict builds and just barge on ahead in
     295 *          release builds.
    193296 */
    194297#ifdef VBOX_STRICT
     
    29803083            case SVGA3D_SURFACE_HINT_INDEXBUFFER:
    29813084            {
    2982                 uint8_t *pData;
    2983                 unsigned uDestOffset;
    2984 
    29853085                Assert(pBoxes[i].h == 1);
    29863086
     3087                VMSVGA3D_CLEAR_GL_ERRORS();
    29873088                pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
    2988                 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
    2989 
    2990                 pData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, (transfer == SVGA3D_READ_HOST_VRAM) ? GL_READ_ONLY : GL_WRITE_ONLY);
    2991                 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
    2992                 Assert(pData);
    2993 
    2994                 uDestOffset = pBoxes[i].x * pSurface->cbBlock + pBoxes[i].y * pMipLevel->cbSurfacePitch;
    2995                 AssertReturn(uDestOffset + pBoxes[i].w * pSurface->cbBlock + (pBoxes[i].h - 1) * pMipLevel->cbSurfacePitch <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
    2996 
    2997                 Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", (fVertex) ? "vertex" : "index", pBoxes[i].x, pBoxes[i].y, pBoxes[i].x + pBoxes[i].w, pBoxes[i].y + pBoxes[i].h));
    2998 
    2999                 rc = vmsvgaGMRTransfer(pThis,
    3000                                        transfer,
    3001                                        pData + uDestOffset,
    3002                                        pMipLevel->cbSurfacePitch,
    3003                                        guest.ptr,
    3004                                        pBoxes[i].srcx * pSurface->cbBlock + pBoxes[i].srcy * cbSrcPitch,
    3005                                        cbSrcPitch,
    3006                                        pBoxes[i].w * pSurface->cbBlock,
    3007                                        pBoxes[i].h);
    3008                 AssertRC(rc);
    3009 
    3010                 Log4(("first line:\n%.*Rhxd\n", cbSrcPitch, pData));
    3011 
    3012                 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
    3013                 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
    3014 
     3089                if (VMSVGA3D_GL_IS_SUCCESS(pContext))
     3090                {
     3091                    GLenum enmGlTransfer = (transfer == SVGA3D_READ_HOST_VRAM) ? GL_READ_ONLY : GL_WRITE_ONLY;
     3092                    uint8_t *pbData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, enmGlTransfer);
     3093                    if (RT_LIKELY(pbData != NULL))
     3094                    {
     3095                        unsigned offDst = pBoxes[i].x * pSurface->cbBlock + pBoxes[i].y * pMipLevel->cbSurfacePitch;
     3096                        if (RT_LIKELY(   offDst + pBoxes[i].w * pSurface->cbBlock  + (pBoxes[i].h - 1) * pMipLevel->cbSurfacePitch
     3097                                      <= pMipLevel->cbSurface))
     3098                        {
     3099                            Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", (fVertex) ? "vertex" : "index",
     3100                                 pBoxes[i].x, pBoxes[i].y, pBoxes[i].x + pBoxes[i].w, pBoxes[i].y + pBoxes[i].h));
     3101
     3102                            rc = vmsvgaGMRTransfer(pThis,
     3103                                                   transfer,
     3104                                                   pbData + offDst,
     3105                                                   pMipLevel->cbSurfacePitch,
     3106                                                   guest.ptr,
     3107                                                   pBoxes[i].srcx * pSurface->cbBlock + pBoxes[i].srcy * cbSrcPitch,
     3108                                                   cbSrcPitch,
     3109                                                   pBoxes[i].w * pSurface->cbBlock,
     3110                                                   pBoxes[i].h);
     3111                            AssertRC(rc);
     3112
     3113                            Log4(("first line:\n%.*Rhxd\n", cbSrcPitch, pbData));
     3114                        }
     3115                        else
     3116                        {
     3117                            AssertFailed();
     3118                            rc = VERR_INTERNAL_ERROR;
     3119                        }
     3120
     3121                        pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
     3122                        VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
     3123                    }
     3124                    else
     3125                        VMSVGA3D_GL_GET_AND_COMPLAIN(pState, pContext, ("glMapBuffer(GL_ARRAY_BUFFER, %#x) -> NULL\n", enmGlTransfer));
     3126                }
     3127                else
     3128                    VMSVGA3D_GL_COMPLAIN(pState, pContext, ("glBindBuffer(GL_ARRAY_BUFFER, %#x)\n", pSurface->oglId.buffer));
    30153129                pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
    30163130                VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
Note: See TracChangeset for help on using the changeset viewer.

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