Exemple #1
0
char* KVStore::getInternal(const std::string& key, char**)
{
    Transaction transaction(*this);
    ScopedReset scopedReset(mGetValueStmt);

    ::sqlite3_bind_text(mGetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);

    int ret = ::sqlite3_step(mGetValueStmt->get());
    if (ret == SQLITE_DONE) {
        throw ConfigException("No value corresponding to the key: " + key + "@" + mPath);
    }
    if (ret != SQLITE_ROW) {
        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
    }

    const char* source = reinterpret_cast<const char*>(sqlite3_column_text(mGetValueStmt->get(), FIRST_COLUMN));

    size_t length = std::strlen(source);
    char* value = new char[length + 1];

    std::strncpy(value, source, length);
    value[length] = '\0';

    transaction.commit();
    return value;
}
Exemple #2
0
void
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
                                WebGLTexture* tex, TexImageTarget target, GLint level,
                                const webgl::DriverUnpackInfo* dui, GLint xOffset,
                                GLint yOffset, GLint zOffset, GLenum* const out_glError)
{
    *out_glError = 0;

    WebGLContext* webgl = tex->mContext;

    // MakeCurrent is a big mess in here, because mapping (and presumably unmapping) on
    // OSX can lose our MakeCurrent. Therefore it's easiest to MakeCurrent just before we
    // call into GL, instead of trying to keep MakeCurrent-ed.

    RefPtr<gfx::DataSourceSurface> dataSurf = mSurf->GetDataSurface();

    if (!dataSurf) {
        // Since GetDataSurface didn't return error code, assume system
        // is out of memory
        *out_glError = LOCAL_GL_OUT_OF_MEMORY;
        return;
    }

    GLenum error;
    if (UploadDataSurface(isSubImage, webgl, target, level, dui, xOffset, yOffset,
                          zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, &error))
    {
        return;
    }
    if (error == LOCAL_GL_OUT_OF_MEMORY) {
        *out_glError = LOCAL_GL_OUT_OF_MEMORY;
        return;
    }

    // CPU conversion. (++numCopies)

    UniqueBuffer convertedBuffer;
    uint8_t convertedAlignment;
    bool outOfMemory;
    if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
                        &convertedAlignment, &outOfMemory))
    {
        if (outOfMemory) {
            *out_glError = LOCAL_GL_OUT_OF_MEMORY;
        } else {
            NS_ERROR("Failed to convert surface.");
            *out_glError = LOCAL_GL_OUT_OF_MEMORY;
        }
        return;
    }

    MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
    ScopedUnpackReset scopedReset(webgl);
    webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);

    error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
                            yOffset, zOffset, mWidth, mHeight, mDepth,
                            convertedBuffer.get());
    *out_glError = error;
}
Exemple #3
0
void KVStore::remove(const std::string& key)
{
    Transaction transaction(*this);
    ScopedReset scopedReset(mRemoveValuesStmt);

    ::sqlite3_bind_text(mRemoveValuesStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);

    if (::sqlite3_step(mRemoveValuesStmt->get()) != SQLITE_DONE) {
        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
    }
    transaction.commit();
}
Exemple #4
0
bool KVStore::isEmpty()
{
    Transaction transaction(*this);
    ScopedReset scopedReset(mGetIsEmptyStmt);

    int ret = ::sqlite3_step(mGetIsEmptyStmt->get());
    if (ret != SQLITE_DONE && ret != SQLITE_ROW) {
        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
    }

    transaction.commit();
    return ret == SQLITE_DONE;
}
Exemple #5
0
bool KVStore::exists(const std::string& key)
{
    Transaction transaction(*this);
    ScopedReset scopedReset(mGetKeyExistsStmt);

    ::sqlite3_bind_text(mGetKeyExistsStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);

    int ret = ::sqlite3_step(mGetKeyExistsStmt->get());
    if (ret != SQLITE_DONE && ret != SQLITE_ROW) {
        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
    }

    transaction.commit();
    return ret == SQLITE_ROW;
}
Exemple #6
0
std::vector<std::string> KVStore::getKeys()
{
    Transaction transaction(*this);
    ScopedReset scopedReset(mGetKeysStmt);

    std::vector<std::string> result;

    for (;;) {
        int ret = ::sqlite3_step(mGetKeysStmt->get());
        if (ret == SQLITE_DONE) {
            break;
        }
        if (ret != SQLITE_ROW) {
            throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
        }
        const char* key = reinterpret_cast<const char*>(sqlite3_column_text(mGetKeysStmt->get(),
                                                                            FIRST_COLUMN));
        result.push_back(key);
    }

    transaction.commit();
    return result;
}
Exemple #7
0
static bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
                TexImageTarget target, uint32_t level,
                const webgl::FormatUsageInfo* usage, uint32_t width, uint32_t height,
                uint32_t depth)
{
    // This has two usecases:
    // 1. Lazy zeroing of uninitialized textures:
    //    a. Before draw, when FakeBlack isn't viable. (TexStorage + Draw*)
    //    b. Before partial upload. (TexStorage + TexSubImage)
    // 2. Zero subrects from out-of-bounds blits. (CopyTex(Sub)Image)

    // We have no sympathy for any of these cases.

    // "Doctor, it hurts when I do this!" "Well don't do that!"
    webgl->GenerateWarning("%s: This operation requires zeroing texture data. This is"
                           " slow.",
                           funcName);

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

    GLenum scopeBindTarget;
    switch (target.get()) {
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
        scopeBindTarget = LOCAL_GL_TEXTURE_CUBE_MAP;
        break;
    default:
        scopeBindTarget = target.get();
        break;
    }
    const gl::ScopedBindTexture scopeBindTexture(gl, tex, scopeBindTarget);
    auto compression = usage->format->compression;
    if (compression) {
        auto sizedFormat = usage->format->sizedFormat;
        MOZ_RELEASE_ASSERT(sizedFormat, "GFX: texture sized format not set");

        const auto fnSizeInBlocks = [](CheckedUint32 pixels, uint8_t pixelsPerBlock) {
            return RoundUpToMultipleOf(pixels, pixelsPerBlock) / pixelsPerBlock;
        };

        const auto widthBlocks = fnSizeInBlocks(width, compression->blockWidth);
        const auto heightBlocks = fnSizeInBlocks(height, compression->blockHeight);

        CheckedUint32 checkedByteCount = compression->bytesPerBlock;
        checkedByteCount *= widthBlocks;
        checkedByteCount *= heightBlocks;
        checkedByteCount *= depth;

        if (!checkedByteCount.isValid())
            return false;

        const size_t byteCount = checkedByteCount.value();

        UniqueBuffer zeros = calloc(1, byteCount);
        if (!zeros)
            return false;

        ScopedUnpackReset scopedReset(webgl);
        gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it
                                                        // well.

        const auto error = DoCompressedTexSubImage(gl, target.get(), level, 0, 0, 0,
                                                   width, height, depth, sizedFormat,
                                                   byteCount, zeros.get());
        return !error;
    }

    const auto driverUnpackInfo = usage->idealUnpack;
    MOZ_RELEASE_ASSERT(driverUnpackInfo, "GFX: ideal unpack info not set.");

    if (webgl->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
        gl->IsANGLE() &&
        usage->format->d)
    {
        // ANGLE_depth_texture does not allow uploads, so we have to clear.
        // (Restriction because of D3D9)
        MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D);
        MOZ_ASSERT(level == 0);
        ZeroANGLEDepthTexture(webgl, tex, usage, width, height);
        return true;
    }

    const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();

    const auto bytesPerPixel = webgl::BytesPerPixel(packing);

    CheckedUint32 checkedByteCount = bytesPerPixel;
    checkedByteCount *= width;
    checkedByteCount *= height;
    checkedByteCount *= depth;

    if (!checkedByteCount.isValid())
        return false;

    const size_t byteCount = checkedByteCount.value();

    UniqueBuffer zeros = calloc(1, byteCount);
    if (!zeros)
        return false;

    ScopedUnpackReset scopedReset(webgl);
    gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
    const auto error = DoTexSubImage(gl, target, level, 0, 0, 0, width, height, depth,
                                     packing, zeros.get());
    return !error;
}
Exemple #8
0
/*static*/ bool
TexUnpackSurface::UploadDataSurface(bool isSubImage, WebGLContext* webgl,
                                    TexImageTarget target, GLint level,
                                    const webgl::DriverUnpackInfo* dui, GLint xOffset,
                                    GLint yOffset, GLint zOffset, GLsizei width,
                                    GLsizei height, gfx::DataSourceSurface* surf,
                                    bool isSurfAlphaPremult, GLenum* const out_glError)
{
    gl::GLContext* gl = webgl->GL();
    MOZ_ASSERT(gl->IsCurrent());
    *out_glError = 0;

    if (isSurfAlphaPremult != webgl->mPixelStore_PremultiplyAlpha)
        return false;

    gl::OriginPos srcOrigin, dstOrigin;
    OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
    if (srcOrigin != dstOrigin)
        return false;

    // This differs from the raw-data upload in that we choose how we do the unpack.
    // (alignment, etc.)

    // Uploading RGBX as RGBA and blitting to RGB is faster than repacking RGBX into
    // RGB on the CPU. However, this is optimization is out-of-scope for now.

    static const webgl::DriverUnpackInfo kInfoBGRA = {
        LOCAL_GL_BGRA,
        LOCAL_GL_BGRA,
        LOCAL_GL_UNSIGNED_BYTE,
    };

    const webgl::DriverUnpackInfo* chosenDUI = nullptr;

    switch (surf->GetFormat()) {
    case gfx::SurfaceFormat::B8G8R8A8:
        if (SupportsBGRA(gl) &&
            dui->internalFormat == LOCAL_GL_RGBA &&
            dui->unpackFormat == LOCAL_GL_RGBA &&
            dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
        {
            chosenDUI = &kInfoBGRA;
        }
        break;

    case gfx::SurfaceFormat::R8G8B8A8:
        if (dui->unpackFormat == LOCAL_GL_RGBA &&
            dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
        {
            chosenDUI = dui;
        }
        break;

    case gfx::SurfaceFormat::R5G6B5_UINT16:
        if (dui->unpackFormat == LOCAL_GL_RGB &&
            dui->unpackType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
        {
            chosenDUI = dui;
        }
        break;

    default:
        break;
    }

    if (!chosenDUI)
        return false;

    gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::MapType::READ);
    if (!map.IsMapped())
        return false;

    const webgl::PackingInfo pi = {chosenDUI->unpackFormat, chosenDUI->unpackType};
    const auto bytesPerPixel = webgl::BytesPerPixel(pi);
    const size_t bytesPerRow = width * bytesPerPixel;

    const GLint kMaxUnpackAlignment = 8;
    size_t unpackAlignment;
    if (!GuessAlignment(map.GetData(), bytesPerRow, map.GetStride(), kMaxUnpackAlignment,
                        &unpackAlignment))
    {
        return false;
        // TODO: Consider using UNPACK_ settings to set the stride based on the too-large
        // alignment used for some SourceSurfaces. (D2D allegedy likes alignment=16)
    }

    MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
    ScopedUnpackReset scopedReset(webgl);
    gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, unpackAlignment);

    const GLsizei depth = 1;
    GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, chosenDUI,
                                   xOffset, yOffset, zOffset, width, height, depth,
                                   map.GetData());
    if (error) {
        *out_glError = error;
        return false;
    }

    return true;
}
static bool ZeroTextureData(const WebGLContext* webgl, GLuint tex,
                            TexImageTarget target, uint32_t level,
                            const webgl::FormatUsageInfo* usage, uint32_t width,
                            uint32_t height, uint32_t depth) {
  // This has two usecases:
  // 1. Lazy zeroing of uninitialized textures:
  //    a. Before draw.
  //    b. Before partial upload. (TexStorage + TexSubImage)
  // 2. Zero subrects from out-of-bounds blits. (CopyTex(Sub)Image)

  // We have no sympathy for any of these cases.

  // "Doctor, it hurts when I do this!" "Well don't do that!"
  const auto targetStr = EnumString(target.get());
  webgl->GeneratePerfWarning(
      "Tex image %s level %u is incurring lazy initialization.",
      targetStr.c_str(), level);

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

  GLenum scopeBindTarget;
  switch (target.get()) {
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
      scopeBindTarget = LOCAL_GL_TEXTURE_CUBE_MAP;
      break;
    default:
      scopeBindTarget = target.get();
      break;
  }
  const gl::ScopedBindTexture scopeBindTexture(gl, tex, scopeBindTarget);
  const auto& compression = usage->format->compression;
  if (compression) {
    auto sizedFormat = usage->format->sizedFormat;
    MOZ_RELEASE_ASSERT(sizedFormat, "GFX: texture sized format not set");

    const auto fnSizeInBlocks = [](CheckedUint32 pixels,
                                   uint8_t pixelsPerBlock) {
      return RoundUpToMultipleOf(pixels, pixelsPerBlock) / pixelsPerBlock;
    };

    const auto widthBlocks = fnSizeInBlocks(width, compression->blockWidth);
    const auto heightBlocks = fnSizeInBlocks(height, compression->blockHeight);

    CheckedUint32 checkedByteCount = compression->bytesPerBlock;
    checkedByteCount *= widthBlocks;
    checkedByteCount *= heightBlocks;
    checkedByteCount *= depth;

    if (!checkedByteCount.isValid()) return false;

    const size_t byteCount = checkedByteCount.value();

    UniqueBuffer zeros = calloc(1, byteCount);
    if (!zeros) return false;

    ScopedUnpackReset scopedReset(webgl);
    gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);  // Don't bother with
                                                     // striding it well.

    const auto error =
        DoCompressedTexSubImage(gl, target.get(), level, 0, 0, 0, width, height,
                                depth, sizedFormat, byteCount, zeros.get());
    return !error;
  }

  const auto driverUnpackInfo = usage->idealUnpack;
  MOZ_RELEASE_ASSERT(driverUnpackInfo, "GFX: ideal unpack info not set.");

  if (usage->format->d) {
    // ANGLE_depth_texture does not allow uploads, so we have to clear.
    // (Restriction because of D3D9)
    // Also, depth resources are cleared to 1.0f and are always renderable, so
    // just use FB clears.
    return ClearDepthTexture(*webgl, tex, target, level, usage, depth);
  }

  const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();

  const auto bytesPerPixel = webgl::BytesPerPixel(packing);

  CheckedUint32 checkedByteCount = bytesPerPixel;
  checkedByteCount *= width;
  checkedByteCount *= height;
  checkedByteCount *= depth;

  if (!checkedByteCount.isValid()) return false;

  const size_t byteCount = checkedByteCount.value();

  UniqueBuffer zeros = calloc(1, byteCount);
  if (!zeros) return false;

  ScopedUnpackReset scopedReset(webgl);
  gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
                   1);  // Don't bother with striding it well.
  const auto error = DoTexSubImage(gl, target, level, 0, 0, 0, width, height,
                                   depth, packing, zeros.get());
  return !error;
}