From 8ae5d2a0490f0479328de82288d4f803cfd9d2f8 Mon Sep 17 00:00:00 2001 From: zhangbin Date: Thu, 13 Feb 2014 16:22:41 +0800 Subject: [PATCH 1/2] closed #3964, Solve the bug of logic code in method Image::saveImageToPNG(). --- cocos/2d/CCRenderTexture.cpp | 4 +-- cocos/2d/platform/CCImageCommon_cpp.h | 36 +++++++++---------- .../RenderTextureTest/RenderTextureTest.cpp | 10 ++---- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/cocos/2d/CCRenderTexture.cpp b/cocos/2d/CCRenderTexture.cpp index 57b6a00d24..5be23d9baa 100644 --- a/cocos/2d/CCRenderTexture.cpp +++ b/cocos/2d/CCRenderTexture.cpp @@ -446,10 +446,10 @@ Image* RenderTexture::newImage(bool fliimage) break; } - this->begin(); + this->onBegin(); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0,0,savedBufferWidth, savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, tempData); - this->end(); + this->onEnd(); if ( fliimage ) // -- flip is only required when saving image to file { diff --git a/cocos/2d/platform/CCImageCommon_cpp.h b/cocos/2d/platform/CCImageCommon_cpp.h index 40eeca0ae7..8e482188e5 100644 --- a/cocos/2d/platform/CCImageCommon_cpp.h +++ b/cocos/2d/platform/CCImageCommon_cpp.h @@ -948,7 +948,7 @@ bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen) } png_read_image(png_ptr, row_pointers); - png_read_end(png_ptr, NULL); + png_read_end(png_ptr, nullptr); _preMulti = false; @@ -1094,7 +1094,7 @@ bool Image::initWithTiffData(const unsigned char * data, ssize_t dataLen) tiffMapProc, tiffUnmapProc); - CC_BREAK_IF(NULL == tif); + CC_BREAK_IF(nullptr == tif); uint32 w = 0, h = 0; uint16 bitsPerSample = 0, samplePerPixel = 0, planarConfig = 0; @@ -1116,7 +1116,7 @@ bool Image::initWithTiffData(const unsigned char * data, ssize_t dataLen) _data = static_cast(malloc(_dataLen * sizeof(unsigned char))); uint32* raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); - if (raster != NULL) + if (raster != nullptr) { if (TIFFReadRGBAImageOriented(tif, w, h, raster, ORIENTATION_TOPLEFT, 0)) { @@ -1851,7 +1851,7 @@ bool Image::initWithWebpData(const unsigned char * data, ssize_t dataLen) if (WebPDecode(static_cast(data), dataLen, &config) != VP8_STATUS_OK) { free(_data); - _data = NULL; + _data = nullptr; break; } @@ -1941,21 +1941,21 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB) png_bytep *row_pointers; fp = fopen(filePath.c_str(), "wb"); - CC_BREAK_IF(NULL == fp); + CC_BREAK_IF(nullptr == fp); - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (NULL == png_ptr) + if (nullptr == png_ptr) { fclose(fp); break; } info_ptr = png_create_info_struct(png_ptr); - if (NULL == info_ptr) + if (nullptr == info_ptr) { fclose(fp); - png_destroy_write_struct(&png_ptr, NULL); + png_destroy_write_struct(&png_ptr, nullptr); break; } #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA && CC_TARGET_PLATFORM != CC_PLATFORM_NACL) @@ -1987,14 +1987,14 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB) png_set_packing(png_ptr); row_pointers = (png_bytep *)malloc(_height * sizeof(png_bytep)); - if(row_pointers == NULL) + if(row_pointers == nullptr) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); break; } - if (hasAlpha()) + if (!hasAlpha()) { for (int i = 0; i < (int)_height; i++) { @@ -2004,14 +2004,14 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB) png_write_image(png_ptr, row_pointers); free(row_pointers); - row_pointers = NULL; + row_pointers = nullptr; } else { if (isToRGB) { unsigned char *pTempData = static_cast(malloc(_width * _height * 3 * sizeof(unsigned char*))); - if (NULL == pTempData) + if (nullptr == pTempData) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); @@ -2036,7 +2036,7 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB) png_write_image(png_ptr, row_pointers); free(row_pointers); - row_pointers = NULL; + row_pointers = nullptr; if (pTempData != nullptr) { @@ -2053,14 +2053,14 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB) png_write_image(png_ptr, row_pointers); free(row_pointers); - row_pointers = NULL; + row_pointers = nullptr; } } png_write_end(png_ptr, info_ptr); png_free(png_ptr, palette); - palette = NULL; + palette = nullptr; png_destroy_write_struct(&png_ptr, &info_ptr); @@ -2085,7 +2085,7 @@ bool Image::saveImageToJPG(const std::string& filePath) /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); - CC_BREAK_IF((outfile = fopen(filePath.c_str(), "wb")) == NULL); + CC_BREAK_IF((outfile = fopen(filePath.c_str(), "wb")) == nullptr); jpeg_stdio_dest(&cinfo, outfile); @@ -2103,7 +2103,7 @@ bool Image::saveImageToJPG(const std::string& filePath) if (hasAlpha()) { unsigned char *pTempData = static_cast(malloc(_width * _height * 3 * sizeof(unsigned char))); - if (NULL == pTempData) + if (nullptr == pTempData) { jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); diff --git a/tests/test-cpp/Classes/RenderTextureTest/RenderTextureTest.cpp b/tests/test-cpp/Classes/RenderTextureTest/RenderTextureTest.cpp index e893f707f7..4203356b7c 100644 --- a/tests/test-cpp/Classes/RenderTextureTest/RenderTextureTest.cpp +++ b/tests/test-cpp/Classes/RenderTextureTest/RenderTextureTest.cpp @@ -143,14 +143,8 @@ void RenderTextureSave::saveImage(cocos2d::Object *sender) _target->saveToFile(png, Image::Format::PNG); _target->saveToFile(jpg, Image::Format::JPG); - - auto image = _target->newImage(); - - auto tex = Director::getInstance()->getTextureCache()->addImage(image, png); - - CC_SAFE_DELETE(image); - - auto sprite = Sprite::createWithTexture(tex); + std::string fileName = FileUtils::getInstance()->getWritablePath() + jpg; + auto sprite = Sprite::create(fileName); sprite->setScale(0.3f); addChild(sprite); From 650331769ab79760795bdb0c8defb3a2e033d471 Mon Sep 17 00:00:00 2001 From: zhangbin Date: Tue, 18 Feb 2014 10:47:14 +0800 Subject: [PATCH 2/2] closed #3964, Use GL methods instead in function RenderTexture::newImage() --- cocos/2d/CCRenderTexture.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/cocos/2d/CCRenderTexture.cpp b/cocos/2d/CCRenderTexture.cpp index 5be23d9baa..fede04c4c3 100644 --- a/cocos/2d/CCRenderTexture.cpp +++ b/cocos/2d/CCRenderTexture.cpp @@ -446,10 +446,23 @@ Image* RenderTexture::newImage(bool fliimage) break; } - this->onBegin(); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); + glBindFramebuffer(GL_FRAMEBUFFER, _FBO); + + //TODO move this to configration, so we don't check it every time + /* Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers. + */ + if (Configuration::getInstance()->checkForGLExtension("GL_QCOM")) + { + // -- bind a temporary texture so we can clear the render buffer without losing our texture + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0); + CHECK_GL_ERROR_DEBUG(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0); + } glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0,0,savedBufferWidth, savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, tempData); - this->onEnd(); + glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); if ( fliimage ) // -- flip is only required when saving image to file {