void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face) { if (mProperties.getMultisampleCount() > 1) BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly."); PixelData myData = lock(GBL_READ_ONLY, mipLevel, face); #if BS_DEBUG_MODE if(dest.getConsecutiveSize() != myData.getConsecutiveSize()) { unlock(); BS_EXCEPT(InternalErrorException, "Buffer sizes don't match"); } #endif PixelUtil::bulkPixelConversion(myData, dest); unlock(); }
void GLTextureBuffer::upload(const PixelData &data, const PixelVolume &dest) { if((mUsage & TU_RENDERTARGET) != 0) BS_EXCEPT(NotImplementedException, "Writing to render texture from CPU not supported."); if ((mUsage & TU_DEPTHSTENCIL) != 0) BS_EXCEPT(NotImplementedException, "Writing to depth stencil texture from CPU not supported."); glBindTexture( mTarget, mTextureID ); if(PixelUtil::isCompressed(data.getFormat())) { if(data.getFormat() != mFormat || !data.isConsecutive()) BS_EXCEPT(InvalidParametersException, "Compressed images must be consecutive, in the source format"); GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat); switch(mTarget) { case GL_TEXTURE_1D: if (dest.left == 0) { glCompressedTexImage1D(GL_TEXTURE_1D, mLevel, format, dest.getWidth(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), format, data.getConsecutiveSize(), data.getData()); } break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: if (dest.left == 0 && dest.top == 0) { glCompressedTexImage2D(mFaceTarget, mLevel, format, dest.getWidth(), dest.getHeight(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), format, data.getConsecutiveSize(), data.getData()); } break; case GL_TEXTURE_3D: if (dest.left == 0 && dest.top == 0 && dest.front == 0) { glCompressedTexImage3D(GL_TEXTURE_3D, mLevel, format, dest.getWidth(), dest.getHeight(), dest.getDepth(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage3D(GL_TEXTURE_3D, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), format, data.getConsecutiveSize(), data.getData()); } break; } } else { if(data.getWidth() != data.getRowPitch()) glPixelStorei(GL_UNPACK_ROW_LENGTH, data.getRowPitch()); if(data.getHeight()*data.getWidth() != data.getSlicePitch()) glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth())); if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0) glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront()); if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); switch(mTarget) { case GL_TEXTURE_1D: glTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: glTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; case GL_TEXTURE_3D: glTexSubImage3D( GL_TEXTURE_3D, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; } } // Restore defaults glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture); }
void GLTextureBuffer::upload(const PixelData& data, const PixelVolume& dest) { if ((mUsage & TU_DEPTHSTENCIL) != 0) { LOGERR("Writing to depth stencil texture from CPU not supported."); return; } glBindTexture(mTarget, mTextureID); BS_CHECK_GL_ERROR(); if(PixelUtil::isCompressed(data.getFormat())) { // Block-compressed data cannot be smaller than 4x4, and must be a multiple of 4 const UINT32 actualWidth = Math::divideAndRoundUp(std::max(mWidth, 4U), 4U) * 4U; const UINT32 actualHeight = Math::divideAndRoundUp(std::max(mHeight, 4U), 4U) * 4U; const UINT32 expectedRowPitch = actualWidth; const UINT32 expectedSlicePitch = actualWidth * actualHeight; const bool isConsecutive = data.getRowPitch() == expectedRowPitch && data.getSlicePitch() == expectedSlicePitch; if (data.getFormat() != mFormat || !isConsecutive) { LOGERR("Compressed images must be consecutive, in the source format"); return; } GLenum format = GLPixelUtil::getGLInternalFormat(mFormat, mHwGamma); switch(mTarget) { case GL_TEXTURE_1D: glCompressedTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), format, data.getConsecutiveSize(), data.getData()); BS_CHECK_GL_ERROR(); break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: glCompressedTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), format, data.getConsecutiveSize(), data.getData()); BS_CHECK_GL_ERROR(); break; case GL_TEXTURE_3D: glCompressedTexSubImage3D(GL_TEXTURE_3D, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), format, data.getConsecutiveSize(), data.getData()); BS_CHECK_GL_ERROR(); break; default: break; } } else { if (data.getWidth() != data.getRowPitch()) { glPixelStorei(GL_UNPACK_ROW_LENGTH, data.getRowPitch()); BS_CHECK_GL_ERROR(); } if (data.getHeight()*data.getWidth() != data.getSlicePitch()) { glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.getSlicePitch() / data.getWidth())); BS_CHECK_GL_ERROR(); } if (data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0) { glPixelStorei( GL_UNPACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront()); BS_CHECK_GL_ERROR(); } if ((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); BS_CHECK_GL_ERROR(); } switch(mTarget) { case GL_TEXTURE_1D: glTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); BS_CHECK_GL_ERROR(); break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: glTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); BS_CHECK_GL_ERROR(); break; case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_3D: glTexSubImage3D( mTarget, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); BS_CHECK_GL_ERROR(); break; } } // Restore defaults glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); BS_CHECK_GL_ERROR(); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); BS_CHECK_GL_ERROR(); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); BS_CHECK_GL_ERROR(); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); BS_CHECK_GL_ERROR(); BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture); }