Exemplo n.º 1
0
std::string EnumString(const GLenum val) {
  const char* name = GetEnumName(val, nullptr);
  if (name) {
    return name;
  }

  const nsPrintfCString hex("<enum 0x%04x>", val);
  return hex.BeginReading();
}
 bool UnlockObject(HANDLE hObject) const {
     bool ret = mWGL->fDXUnlockObjects(mDXGLDeviceHandle, 1, &hObject);
     if (!ret) {
         uint32_t error = GetLastError();
         const nsPrintfCString errorMessage("wglDXUnlockObjects(0x%x, 1, {0x%x}) "
                                            "failed: GetLastError(): 0x%x\n",
                                            mDXGLDeviceHandle, hObject, error);
         gfxCriticalError() << errorMessage.BeginReading();
         MOZ_CRASH("GFX: Problem unlocking DXGL device");
     }
     return ret;
 }
Exemplo n.º 3
0
void WebGLContext::ErrorImplementationBug(const char* fmt, ...) const {
  const nsPrintfCString warning("Implementation bug, please file at %s! %s",
                                "https://bugzilla.mozilla.org/", fmt);

  va_list va;
  va_start(va, fmt);
  GenerateWarning(warning.BeginReading(), va);
  va_end(va);

  MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
  NS_ERROR("WebGLContext::ErrorImplementationBug");
  return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
}
Exemplo n.º 4
0
bool
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
                              WebGLTexture* tex, TexImageTarget target, GLint level,
                              const webgl::DriverUnpackInfo* dui, GLint xOffset,
                              GLint yOffset, GLint zOffset, const webgl::PackingInfo& pi,
                              GLenum* const out_error) const
{
    MOZ_ASSERT_IF(needsRespec, !isSubImage);

    WebGLContext* webgl = tex->mContext;

    gl::GLContext* gl = webgl->GL();
    gl->MakeCurrent();

    if (needsRespec) {
        *out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
                                     yOffset, zOffset, mWidth, mHeight, mDepth,
                                     nullptr);
        if (*out_error)
            return true;
    }

    const char* fallbackReason;
    do {
        if (mDepth != 1) {
            fallbackReason = "depth is not 1";
            break;
        }

        if (webgl->mPixelStore_UnpackSkipPixels ||
            webgl->mPixelStore_UnpackSkipRows ||
            webgl->mPixelStore_UnpackSkipImages)
        {
            fallbackReason = "non-zero UNPACK_SKIP_* not yet supported";
            break;
        }

        const auto fnHasPremultMismatch = [&]() {
            if (mSrcAlphaType == gfxAlphaType::Opaque)
                return false;

            const bool srcIsPremult = (mSrcAlphaType == gfxAlphaType::Premult);
            const auto& dstIsPremult = webgl->mPixelStore_PremultiplyAlpha;
            if (srcIsPremult == dstIsPremult)
                return false;

            if (dstIsPremult) {
                fallbackReason = "UNPACK_PREMULTIPLY_ALPHA_WEBGL is not true";
            } else {
                fallbackReason = "UNPACK_PREMULTIPLY_ALPHA_WEBGL is not false";
            }
            return true;
        };
        if (fnHasPremultMismatch())
            break;

        if (dui->unpackFormat != LOCAL_GL_RGB && dui->unpackFormat != LOCAL_GL_RGBA) {
            fallbackReason = "`format` is not RGB or RGBA";
            break;
        }

        if (dui->unpackType != LOCAL_GL_UNSIGNED_BYTE) {
            fallbackReason = "`type` is not UNSIGNED_BYTE";
            break;
        }

        gl::ScopedFramebuffer scopedFB(gl);
        gl::ScopedBindFramebuffer bindFB(gl, scopedFB.FB());

        {
            gl::GLContext::LocalErrorScope errorScope(*gl);

            gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
                                      target.get(), tex->mGLName, level);

            if (errorScope.GetError()) {
                fallbackReason = "bug: failed to attach to FB for blit";
                break;
            }
        }

        const GLenum status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
        if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
            fallbackReason = "bug: failed to confirm FB for blit";
            break;
        }

        const gfx::IntSize destSize(mWidth, mHeight);
        const auto dstOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
                                                         : gl::OriginPos::BottomLeft);
        if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, scopedFB.FB(),
                                                      dstOrigin))
        {
            fallbackReason = "likely bug: failed to blit";
            break;
        }

        // Blitting was successful, so we're done!
        *out_error = 0;
        return true;
    } while (false);

    const nsPrintfCString perfMsg("%s: Failed to hit GPU-copy fast-path: %s (src type %u)",
                                  funcName, fallbackReason, uint32_t(mImage->GetFormat()));

    if (webgl->mPixelStore_RequireFastPath) {
        webgl->ErrorInvalidOperation("%s", perfMsg.BeginReading());
        return false;
    }

    webgl->GeneratePerfWarning("%s Falling back to CPU upload.",
                               perfMsg.BeginReading());

    const RefPtr<gfx::SourceSurface> surf = mImage->GetAsSourceSurface();

    RefPtr<gfx::DataSourceSurface> dataSurf;
    if (surf) {
        // WARNING: OSX can lose our MakeCurrent here.
        dataSurf = surf->GetDataSurface();
    }
    if (!dataSurf) {
        webgl->ErrorOutOfMemory("%s: GetAsSourceSurface or GetDataSurface failed after"
                                " blit failed for TexUnpackImage.",
                                funcName);
        return false;
    }

    const TexUnpackSurface surfBlob(webgl, target, mWidth, mHeight, mDepth, dataSurf,
                                    mSrcAlphaType);

    return surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level,
                                  dui, xOffset, yOffset, zOffset, pi, out_error);
}
Exemplo n.º 5
0
bool
GLBlitHelper::BlitImage(layers::MacIOSurfaceImage* const srcImage,
                        const gfx::IntSize& destSize, const OriginPos destOrigin) const
{
    MacIOSurface* const iosurf = srcImage->GetSurface();
    if (mGL->GetContextType() != GLContextType::CGL) {
        MOZ_ASSERT(false);
        return false;
    }
    const auto glCGL = static_cast<GLContextCGL*>(mGL);
    const auto cglContext = glCGL->GetCGLContext();

    const auto& srcOrigin = OriginPos::BottomLeft;

    DrawBlitProg::BaseArgs baseArgs;
    baseArgs.yFlip = (destOrigin != srcOrigin);
    baseArgs.destSize = destSize;

    DrawBlitProg::YUVArgs yuvArgs;
    yuvArgs.colorSpace = YUVColorSpace::BT601;

    const DrawBlitProg::YUVArgs* pYuvArgs = nullptr;

    auto planes = iosurf->GetPlaneCount();
    if (!planes) {
        planes = 1; // Bad API. No cookie.
    }

    const GLenum texTarget = LOCAL_GL_TEXTURE_RECTANGLE;
    const char* const fragHeader = kFragHeader_Tex2DRect;

    const ScopedSaveMultiTex saveTex(mGL, planes, texTarget);
    const ScopedTexture tex0(mGL);
    const ScopedTexture tex1(mGL);
    const ScopedTexture tex2(mGL);
    const GLuint texs[3] = {
        tex0,
        tex1,
        tex2
    };

    const auto pixelFormat = iosurf->GetPixelFormat();
    const auto formatChars = (const char*)&pixelFormat;
    const char formatStr[] = {
        formatChars[3],
        formatChars[2],
        formatChars[1],
        formatChars[0],
        0
    };
    if (mGL->ShouldSpew()) {
        printf_stderr("iosurf format: %s (0x%08x)\n", formatStr, uint32_t(pixelFormat));
    }

    const char* fragBody;
    GLenum internalFormats[3] = {0, 0, 0};
    GLenum unpackFormats[3] = {0, 0, 0};
    GLenum unpackTypes[3] = { LOCAL_GL_UNSIGNED_BYTE,
                              LOCAL_GL_UNSIGNED_BYTE,
                              LOCAL_GL_UNSIGNED_BYTE };
    switch (planes) {
    case 1:
        fragBody = kFragBody_RGBA;
        internalFormats[0] = LOCAL_GL_RGBA;
        unpackFormats[0] = LOCAL_GL_RGBA;
        break;
    case 2:
        fragBody = kFragBody_NV12;
        if (mGL->Version() >= 300) {
            internalFormats[0] = LOCAL_GL_R8;
            unpackFormats[0] = LOCAL_GL_RED;
            internalFormats[1] = LOCAL_GL_RG8;
            unpackFormats[1] = LOCAL_GL_RG;
        } else {
            internalFormats[0] = LOCAL_GL_LUMINANCE;
            unpackFormats[0] = LOCAL_GL_LUMINANCE;
            internalFormats[1] = LOCAL_GL_LUMINANCE_ALPHA;
            unpackFormats[1] = LOCAL_GL_LUMINANCE_ALPHA;
        }
        pYuvArgs = &yuvArgs;
        break;
    case 3:
        fragBody = kFragBody_PlanarYUV;
        if (mGL->Version() >= 300) {
            internalFormats[0] = LOCAL_GL_R8;
            unpackFormats[0] = LOCAL_GL_RED;
        } else {
            internalFormats[0] = LOCAL_GL_LUMINANCE;
            unpackFormats[0] = LOCAL_GL_LUMINANCE;
        }
        internalFormats[1] = internalFormats[0];
        internalFormats[2] = internalFormats[0];
        unpackFormats[1] = unpackFormats[0];
        unpackFormats[2] = unpackFormats[0];
        pYuvArgs = &yuvArgs;
        break;
    default:
        gfxCriticalError() << "Unexpected plane count: " << planes;
        return false;
    }

    if (pixelFormat == '2vuy') {
        fragBody = kFragBody_CrYCb;
        // APPLE_rgb_422 adds RGB_RAW_422_APPLE for `internalFormat`, but only RGB seems
        // to work?
        internalFormats[0] = LOCAL_GL_RGB;
        unpackFormats[0] = LOCAL_GL_RGB_422_APPLE;
        unpackTypes[0] = LOCAL_GL_UNSIGNED_SHORT_8_8_APPLE;
        pYuvArgs = &yuvArgs;
    }

    for (uint32_t p = 0; p < planes; p++) {
        mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + p);
        mGL->fBindTexture(texTarget, texs[p]);
        mGL->TexParams_SetClampNoMips(texTarget);

        const auto width = iosurf->GetDevicePixelWidth(p);
        const auto height = iosurf->GetDevicePixelHeight(p);
        auto err = iosurf->CGLTexImageIOSurface2D(cglContext, texTarget,
                                                  internalFormats[p], width, height,
                                                  unpackFormats[p], unpackTypes[p], p);
        if (err) {
            const nsPrintfCString errStr("CGLTexImageIOSurface2D(context, target, 0x%04x,"
                                         " %u, %u, 0x%04x, 0x%04x, iosurfPtr, %u) -> %i",
                                         internalFormats[p], uint32_t(width),
                                         uint32_t(height), unpackFormats[p],
                                         unpackTypes[p], p, err);
            gfxCriticalError() << errStr.get() << " (iosurf format: " << formatStr << ")";
            return false;
        }

        if (p == 0) {
            baseArgs.texMatrix0 = SubRectMat3(0, 0, width, height);
            yuvArgs.texMatrix1 = SubRectMat3(0, 0, width / 2.0, height / 2.0);
        }
    }

    const auto& prog = GetDrawBlitProg({fragHeader, fragBody});
    if (!prog)
        return false;

    prog->Draw(baseArgs, pYuvArgs);
    return true;
}
Exemplo n.º 6
0
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
                                                 FakeBlackType type)
    : mGL(gl)
    , mGLName(CreateGLTexture(gl))
{
    GLenum texFormat;
    switch (type) {
    case FakeBlackType::RGBA0000:
        texFormat = LOCAL_GL_RGBA;
        break;

    case FakeBlackType::RGBA0001:
        texFormat = LOCAL_GL_RGB;
        break;

    default:
        MOZ_CRASH("bad type");
    }

    gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());

    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);

    // We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
    // minimize the risk of running into a driver bug in texImage2D, as it is a bit
    // unusual maybe to create 1x1 textures, and the stack may not have the alignment that
    // TexImage2D expects.

    const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
    UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.

    MOZ_ASSERT(gl->IsCurrent());
    if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
        for (int i = 0; i < 6; ++i) {
            const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
            const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
                                            zeros.get());
            if (error) {
                const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                           "for `curTarget`: 0x%04x, "
                                           "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                           error, curTarget.get(), dui.internalFormat,
                                           dui.unpackFormat, dui.unpackType);
                gfxCriticalError() << text.BeginReading();
                MOZ_CRASH("Unexpected error during cube map FakeBlack creation.");
            }
        }
    } else {
        const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
                                        zeros.get());
        if (error) {
            const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                       "for `target`: 0x%04x, "
                                       "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                       error, target.get(), dui.internalFormat,
                                       dui.unpackFormat, dui.unpackType);
            gfxCriticalError() << text.BeginReading();
            MOZ_CRASH("Unexpected error during FakeBlack creation.");
        }
    }
}