void GraphicsContext3D::readPixelsIMG(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
{
    // Currently only format=RGBA, type=UNSIGNED_BYTE is supported by the specification: http://www.khronos.org/registry/webgl/specs/latest/
    // If this ever changes, this code will need to be updated.

    // Calculate the strides of our data and canvas
    unsigned formatSize = 4; // RGBA UNSIGNED_BYTE
    unsigned dataStride = width * formatSize;
    unsigned canvasStride = m_currentWidth * formatSize;

    // If we are using a pack alignment of 8, then we need to align our strides to 8 byte boundaries
    // See: http://en.wikipedia.org/wiki/Data_structure_alignment (computing padding)
    int packAlignment;
    glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment);
    if (8 == packAlignment) {
        dataStride = (dataStride + 7) & ~7;
        canvasStride = (canvasStride + 7) & ~7;
    }

    unsigned char* canvasData = new unsigned char[canvasStride * m_currentHeight];
    ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, format, type, canvasData);

    // If we failed to read our canvas data due to a GL error, don't continue
    int error = glGetError();
    if (GL_NO_ERROR != error) {
        synthesizeGLError(error);
        return;
    }

    // Clear our data in case some of it lies outside the bounds of our canvas
    // TODO: don't do this if all of the data lies inside the bounds of the canvas
    memset(data, 0, dataStride * height);

    // Calculate the intersection of our canvas and data bounds
    IntRect dataRect(x, y, width, height);
    IntRect canvasRect(0, 0, m_currentWidth, m_currentHeight);
    IntRect nonZeroDataRect = intersection(dataRect, canvasRect);

    unsigned xDataOffset = x < 0 ? -x * formatSize : 0;
    unsigned yDataOffset = y < 0 ? -y * dataStride : 0;
    unsigned xCanvasOffset = nonZeroDataRect.x() * formatSize;
    unsigned yCanvasOffset = nonZeroDataRect.y() * canvasStride;
    unsigned char* dst = static_cast<unsigned char*>(data) + xDataOffset + yDataOffset;
    unsigned char* src = canvasData + xCanvasOffset + yCanvasOffset;
    for (int row = 0; row < nonZeroDataRect.height(); row++) {
        memcpy(dst, src, nonZeroDataRect.width() * formatSize);
        dst += dataStride;
        src += canvasStride;
    }

    delete [] canvasData;
}
Exemple #2
0
Vec2 g_randomPosition(const Vec2& posStart)
{
    Size winSize = Director::getInstance()->getWinSize();
    Rect canvasRect(0.0f, 0.0f, winSize.width-100.0f, winSize.height-200.0f);
    return g_randomPosition(posStart, canvasRect);
}