Ejemplo n.º 1
0
gfx::DrawTarget*
BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
{
    NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");

    // determine the region the client will need to repaint
    if (CanUploadSubTextures(mGLContext)) {
        GetUpdateRegion(aRegion);
    } else {
        aRegion = IntRect(IntPoint(0, 0), mSize);
    }

    mUpdateRegion = aRegion;

    IntRect rgnSize = mUpdateRegion.GetBounds();
    if (!IntRect(IntPoint(0, 0), mSize).Contains(rgnSize)) {
        NS_ERROR("update outside of image");
        return nullptr;
    }

    gfx::SurfaceFormat format =
        (GetContentType() == gfxContentType::COLOR) ?
        gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
    mUpdateDrawTarget =
        GetDrawTargetForUpdate(gfx::IntSize(rgnSize.width, rgnSize.height), format);

    return mUpdateDrawTarget;
}
Ejemplo n.º 2
0
bool
TiledTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0, 0) */)
{
    if (mSize.width == 0 || mSize.height == 0) {
        return true;
    }

    nsIntRegion region;

    if (mTextureState != Valid) {
        IntRect bounds = IntRect(0, 0, mSize.width, mSize.height);
        region = nsIntRegion(bounds);
    } else {
        region = aRegion;
    }

    bool result = true;
    int oldCurrentImage = mCurrentImage;
    BeginBigImageIteration();
    do {
        IntRect tileRect = GetSrcTileRect();
        int xPos = tileRect.x;
        int yPos = tileRect.y;

        nsIntRegion tileRegion;
        tileRegion.And(region, tileRect); // intersect with tile

        if (tileRegion.IsEmpty())
            continue;

        if (CanUploadSubTextures(mGL)) {
          tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
        } else {
          // If sub-textures are unsupported, expand to tile boundaries
          tileRect.x = tileRect.y = 0;
          tileRegion = nsIntRegion(tileRect);
        }

        result &= mImages[mCurrentImage]->
          DirectUpdate(aSurf, tileRegion, aFrom + gfx::IntPoint(xPos, yPos));

        if (mCurrentImage == mImages.Length() - 1) {
            // We know we're done, but we still need to ensure that the callback
            // gets called (e.g. to update the uploaded region).
            NextTile();
            break;
        }
        // Override a callback cancelling iteration if the texture wasn't valid.
        // We need to force the update in that situation, or we may end up
        // showing invalid/out-of-date texture data.
    } while (NextTile() || (mTextureState != Valid));
    mCurrentImage = oldCurrentImage;

    mTextureFormat = mImages[0]->GetTextureFormat();
    mTextureState = Valid;
    return result;
}
Ejemplo n.º 3
0
static bool
WantsSmallTiles(GLContext* gl)
{
    // We must use small tiles for good performance if we can't use
    // glTexSubImage2D() for some reason.
    if (!CanUploadSubTextures(gl))
        return true;

    // We can't use small tiles on the SGX 540, because of races in texture upload.
    if (gl->WorkAroundDriverBugs() &&
        gl->Renderer() == GLRenderer::SGX540)
        return false;

    // Don't use small tiles otherwise. (If we implement incremental texture upload,
    // then we will want to revisit this.)
    return false;
}
Ejemplo n.º 4
0
SurfaceFormat
UploadImageDataToTexture(GLContext* gl,
                         unsigned char* aData,
                         int32_t aStride,
                         gfxImageFormat aFormat,
                         const nsIntRegion& aDstRegion,
                         GLuint& aTexture,
                         bool aOverwrite,
                         bool aPixelBuffer,
                         GLenum aTextureUnit,
                         GLenum aTextureTarget)
{
    bool textureInited = aOverwrite ? false : true;
    gl->MakeCurrent();
    gl->fActiveTexture(aTextureUnit);

    if (!aTexture) {
        gl->fGenTextures(1, &aTexture);
        gl->fBindTexture(aTextureTarget, aTexture);
        gl->fTexParameteri(aTextureTarget,
                           LOCAL_GL_TEXTURE_MIN_FILTER,
                           LOCAL_GL_LINEAR);
        gl->fTexParameteri(aTextureTarget,
                           LOCAL_GL_TEXTURE_MAG_FILTER,
                           LOCAL_GL_LINEAR);
        gl->fTexParameteri(aTextureTarget,
                           LOCAL_GL_TEXTURE_WRAP_S,
                           LOCAL_GL_CLAMP_TO_EDGE);
        gl->fTexParameteri(aTextureTarget,
                           LOCAL_GL_TEXTURE_WRAP_T,
                           LOCAL_GL_CLAMP_TO_EDGE);
        textureInited = false;
    } else {
        gl->fBindTexture(aTextureTarget, aTexture);
    }

    nsIntRegion paintRegion;
    if (!textureInited) {
        paintRegion = nsIntRegion(aDstRegion.GetBounds());
    } else {
        paintRegion = aDstRegion;
    }

    GLenum format;
    GLenum internalFormat;
    GLenum type;
    int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
    SurfaceFormat surfaceFormat;

    MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
               gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
    switch (aFormat) {
        case gfxImageFormatARGB32:
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              format = LOCAL_GL_BGRA;
              surfaceFormat = gfx::FORMAT_R8G8B8A8;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
            } else {
              format = LOCAL_GL_RGBA;
              surfaceFormat = gfx::FORMAT_B8G8R8A8;
              type = LOCAL_GL_UNSIGNED_BYTE;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case gfxImageFormatRGB24:
            // Treat RGB24 surfaces as RGBA32 except for the surface
            // format used.
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              format = LOCAL_GL_BGRA;
              surfaceFormat = gfx::FORMAT_R8G8B8X8;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
            } else {
              format = LOCAL_GL_RGBA;
              surfaceFormat = gfx::FORMAT_B8G8R8X8;
              type = LOCAL_GL_UNSIGNED_BYTE;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case gfxImageFormatRGB16_565:
            internalFormat = format = LOCAL_GL_RGB;
            type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
            surfaceFormat = gfx::FORMAT_R5G6B5;
            break;
        case gfxImageFormatA8:
            internalFormat = format = LOCAL_GL_LUMINANCE;
            type = LOCAL_GL_UNSIGNED_BYTE;
            // We don't have a specific luminance shader
            surfaceFormat = gfx::FORMAT_A8;
            break;
        default:
            NS_ASSERTION(false, "Unhandled image surface format!");
            format = 0;
            type = 0;
            surfaceFormat = gfx::FORMAT_UNKNOWN;
    }

    nsIntRegionRectIterator iter(paintRegion);
    const nsIntRect *iterRect;

    // Top left point of the region's bounding rectangle.
    nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();

    while ((iterRect = iter.Next())) {
        // The inital data pointer is at the top left point of the region's
        // bounding rectangle. We need to find the offset of this rect
        // within the region and adjust the data pointer accordingly.
        unsigned char *rectData =
            aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);

        NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
                     "Must be uploading to the origin when we don't have an existing texture");

        if (textureInited && CanUploadSubTextures(gl)) {
            TexSubImage2DHelper(gl,
                                aTextureTarget,
                                0,
                                iterRect->x,
                                iterRect->y,
                                iterRect->width,
                                iterRect->height,
                                aStride,
                                pixelSize,
                                format,
                                type,
                                rectData);
        } else {
            TexImage2DHelper(gl,
                             aTextureTarget,
                             0,
                             internalFormat,
                             iterRect->width,
                             iterRect->height,
                             aStride,
                             pixelSize,
                             0,
                             format,
                             type,
                             rectData);
        }

    }

    return surfaceFormat;
}
Ejemplo n.º 5
0
SurfaceFormat
UploadImageDataToTexture(GLContext* gl,
                         unsigned char* aData,
                         int32_t aStride,
                         SurfaceFormat aFormat,
                         const nsIntRegion& aDstRegion,
                         GLuint aTexture,
                         const gfx::IntSize& aSize,
                         size_t* aOutUploadSize,
                         bool aNeedInit,
                         GLenum aTextureUnit,
                         GLenum aTextureTarget)
{
    gl->MakeCurrent();
    gl->fActiveTexture(aTextureUnit);
    gl->fBindTexture(aTextureTarget, aTexture);

    GLenum format = 0;
    GLenum internalFormat = 0;
    GLenum type = 0;
    int32_t pixelSize = BytesPerPixel(aFormat);
    SurfaceFormat surfaceFormat = gfx::SurfaceFormat::UNKNOWN;

    MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
               gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);

    switch (aFormat) {
        case SurfaceFormat::B8G8R8A8:
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              format = LOCAL_GL_BGRA;
              surfaceFormat = SurfaceFormat::R8G8B8A8;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
            } else {
              format = LOCAL_GL_RGBA;
              surfaceFormat = SurfaceFormat::B8G8R8A8;
              type = LOCAL_GL_UNSIGNED_BYTE;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case SurfaceFormat::B8G8R8X8:
            // Treat BGRX surfaces as BGRA except for the surface
            // format used.
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              format = LOCAL_GL_BGRA;
              surfaceFormat = SurfaceFormat::R8G8B8X8;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
            } else {
              format = LOCAL_GL_RGBA;
              surfaceFormat = SurfaceFormat::B8G8R8X8;
              type = LOCAL_GL_UNSIGNED_BYTE;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case SurfaceFormat::R8G8B8A8:
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              // Upload our RGBA as BGRA, but store that the uploaded format is
              // BGRA. (sample from R to get B)
              format = LOCAL_GL_BGRA;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
              surfaceFormat = SurfaceFormat::B8G8R8A8;
            } else {
              format = LOCAL_GL_RGBA;
              type = LOCAL_GL_UNSIGNED_BYTE;
              surfaceFormat = SurfaceFormat::R8G8B8A8;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case SurfaceFormat::R8G8B8X8:
            // Treat RGBX surfaces as RGBA except for the surface
            // format used.
            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
              format = LOCAL_GL_BGRA;
              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
              surfaceFormat = SurfaceFormat::B8G8R8X8;
            } else {
              format = LOCAL_GL_RGBA;
              type = LOCAL_GL_UNSIGNED_BYTE;
              surfaceFormat = SurfaceFormat::R8G8B8X8;
            }
            internalFormat = LOCAL_GL_RGBA;
            break;
        case SurfaceFormat::R5G6B5_UINT16:
            internalFormat = format = LOCAL_GL_RGB;
            type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
            surfaceFormat = SurfaceFormat::R5G6B5_UINT16;
            break;
        case SurfaceFormat::A8:
            internalFormat = format = LOCAL_GL_LUMINANCE;
            type = LOCAL_GL_UNSIGNED_BYTE;
            // We don't have a specific luminance shader
            surfaceFormat = SurfaceFormat::A8;
            break;
        default:
            NS_ASSERTION(false, "Unhandled image surface format!");
    }

    if (aOutUploadSize) {
        *aOutUploadSize = 0;
    }

    if (aNeedInit || !CanUploadSubTextures(gl)) {
        // If the texture needs initialized, or we are unable to
        // upload sub textures, then initialize and upload the entire
        // texture.
        TexImage2DHelper(gl,
                         aTextureTarget,
                         0,
                         internalFormat,
                         aSize.width,
                         aSize.height,
                         aStride,
                         pixelSize,
                         0,
                         format,
                         type,
                         aData);

        if (aOutUploadSize && aNeedInit) {
            uint32_t texelSize = GetBytesPerTexel(internalFormat, type);
            size_t numTexels = size_t(aSize.width) * size_t(aSize.height);
            *aOutUploadSize += texelSize * numTexels;
        }
    } else {
        // Upload each rect in the region to the texture
        for (auto iter = aDstRegion.RectIter(); !iter.Done(); iter.Next()) {
            const IntRect& rect = iter.Get();
            const unsigned char* rectData =
                aData + DataOffset(rect.TopLeft(), aStride, aFormat);

            TexSubImage2DHelper(gl,
                                aTextureTarget,
                                0,
                                rect.x,
                                rect.y,
                                rect.Width(),
                                rect.Height(),
                                aStride,
                                pixelSize,
                                format,
                                type,
                                rectData);
        }
    }

    return surfaceFormat;
}