/*========================================================================= Program: Visualization Toolkit Module: vtkCompositeRGBAPass.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkCompositeRGBAPass.h" #include "vtkObjectFactory.h" #include #include "vtkRenderState.h" #include "vtkOpenGLRenderer.h" #include "vtkFrameBufferObjectBase.h" #include "vtkTextureObject.h" #include "vtkOpenGLRenderWindow.h" // to be able to dump intermediate result into png files for debugging. // only for vtkCompositeRGBAPass developers. //#define VTK_COMPOSITE_RGBAPASS_DEBUG #include "vtkPNGWriter.h" #include "vtkImageImport.h" #include "vtkImageShiftScale.h" #include "vtkPixelBufferObject.h" #include "vtkImageExtractComponents.h" #include "vtkMultiProcessController.h" #include #include "vtkTimerLog.h" #include "vtkStdString.h" #include "vtkImageData.h" #include "vtkPointData.h" #include "vtkPKdTree.h" #include "vtkCamera.h" #include "vtkIntArray.h" #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG //#include # include # include // Linux specific gettid() # include "vtkOpenGLState.h" #endif #ifdef VTK_OPENGL2 # include "vtk_glew.h" #else # include "vtkFrameBufferObject.h" # include "vtkgl.h" # include "vtkOpenGLExtensionManager.h" #endif vtkStandardNewMacro(vtkCompositeRGBAPass); vtkCxxSetObjectMacro(vtkCompositeRGBAPass,Controller,vtkMultiProcessController); vtkCxxSetObjectMacro(vtkCompositeRGBAPass,Kdtree,vtkPKdTree); // ---------------------------------------------------------------------------- vtkCompositeRGBAPass::vtkCompositeRGBAPass() { this->Controller=nullptr; this->Kdtree=nullptr; this->PBO=nullptr; this->RGBATexture=nullptr; this->RootTexture=nullptr; this->RawRGBABuffer=nullptr; this->RawRGBABufferSize=0; } // ---------------------------------------------------------------------------- vtkCompositeRGBAPass::~vtkCompositeRGBAPass() { if(this->Controller!=nullptr) { this->Controller->Delete(); } if(this->Kdtree!=nullptr) { this->Kdtree->Delete(); } if(this->PBO!=nullptr) { vtkErrorMacro(<<"PixelBufferObject should have been deleted in ReleaseGraphicsResources()."); } if(this->RGBATexture!=nullptr) { vtkErrorMacro(<<"RGBATexture should have been deleted in ReleaseGraphicsResources()."); } if(this->RootTexture!=nullptr) { vtkErrorMacro(<<"RootTexture should have been deleted in ReleaseGraphicsResources()."); } delete[] this->RawRGBABuffer; } // ---------------------------------------------------------------------------- void vtkCompositeRGBAPass::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Controller:"; if(this->Controller!=nullptr) { this->Controller->PrintSelf(os,indent); } else { os << "(none)" <Kdtree!=nullptr) { this->Kdtree->PrintSelf(os,indent); } else { os << "(none)" <GetExtensionManager(); bool fbo_support=vtkFrameBufferObject::IsSupported(context); bool texture_support = vtkTextureObject::IsSupported(context) && (extmgr->ExtensionSupported("GL_ARB_texture_float")==1); return fbo_support && texture_support; #endif } // ---------------------------------------------------------------------------- // Description: // Perform rendering according to a render state \p s. // \pre s_exists: s!=0 void vtkCompositeRGBAPass::Render(const vtkRenderState *s) { assert("pre: s_exists" && s!=nullptr); if(this->Controller==nullptr) { vtkErrorMacro(<<" no controller."); return; } int numProcs=this->Controller->GetNumberOfProcesses(); if(numProcs==1) { return; // nothing to do. } if(this->Kdtree==nullptr) { vtkErrorMacro(<<" no Kdtree."); return; } int me=this->Controller->GetLocalProcessId(); const int VTK_COMPOSITE_RGBA_PASS_MESSAGE_GATHER=201; vtkOpenGLRenderer *r = static_cast(s->GetRenderer()); vtkOpenGLRenderWindow *context = static_cast(r->GetRenderWindow()); if (!this->IsSupported(context)) { vtkErrorMacro( << "Missing required OpenGL extensions. " << "Cannot perform rgba-compositing."); return; } #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG vtkOpenGLState *state=new vtkOpenGLState(context); #endif int w=0; int h=0; vtkFrameBufferObjectBase *fbo = s->GetFrameBuffer(); if(fbo==nullptr) { r->GetTiledSize(&w,&h); } else { int size[2]; fbo->GetLastSize(size); w=size[0]; h=size[1]; } int numComps = 4; unsigned int numTups = w*h; // pbo arguments. unsigned int dims[2]; vtkIdType continuousInc[3]; dims[0]=static_cast(w); dims[1]=static_cast(h); continuousInc[0]=0; continuousInc[1]=0; continuousInc[2]=0; if(this->RawRGBABuffer!=nullptr && this->RawRGBABufferSize(w*h*4)) { delete[] this->RawRGBABuffer; this->RawRGBABuffer=nullptr; } if(this->RawRGBABuffer==nullptr) { this->RawRGBABufferSize=static_cast(w*h*4); this->RawRGBABuffer=new float[this->RawRGBABufferSize]; } //size_t byteSize = this->RawRGBABufferSize*sizeof(unsigned char); if(this->PBO==nullptr) { this->PBO=vtkPixelBufferObject::New(); this->PBO->SetContext(context); } if(this->RGBATexture==nullptr) { this->RGBATexture=vtkTextureObject::New(); this->RGBATexture->SetContext(context); } // TO: texture object // PBO: pixel buffer object // FB: framebuffer #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG vtkTimerLog *timer=vtkTimerLog::New(); vtkImageImport *importer; vtkImageShiftScale *converter; vtkPNGWriter *writer; cout << "me=" << me<< " TID="<< syscall(SYS_gettid) << " thread=" << pthread_self() << endl; timer->StartTimer(); #endif if(me==0) { // root // 1. figure out the back to front ordering // 2. if root is not farest, save it in a TO // 3. in back to front order: // 3a. if this is step for root, render root TO (if not farest) // 3b. if satellite, get image, load it into TO, render quad #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG // get rgba-buffer of root before any blending with satellite // for debugging only. // Framebuffer to PBO this->PBO->Allocate( VTK_FLOAT, numTups, numComps, vtkPixelBufferObject::PACKED_BUFFER); this->PBO->Bind(vtkPixelBufferObject::PACKED_BUFFER); glReadPixels(0,0,w,h,GL_RGBA,GL_FLOAT, static_cast(nullptr)); cout << "after readpixel." << endl; this->PBO->Download2D(VTK_FLOAT,this->RawRGBABuffer,dims,4,continuousInc); cout << "after pbodownload." << endl; importer=vtkImageImport::New(); importer->CopyImportVoidPointer(this->RawRGBABuffer, static_cast(byteSize)); importer->SetDataScalarTypeToFloat(); importer->SetNumberOfScalarComponents(4); importer->SetWholeExtent(0,w-1,0,h-1,0,0); importer->SetDataExtentToWholeExtent(); importer->Update(); cout << "after importer update" << endl; converter=vtkImageShiftScale::New(); converter->SetInputConnection(importer->GetOutputPort()); converter->SetOutputScalarTypeToUnsignedChar(); converter->SetShift(0.0); converter->SetScale(255.0); // vtkImageExtractComponents *rgbaToRgb=vtkImageExtractComponents::New(); // rgbaToRgb->SetInputConnection(importer->GetOutputPort()); // rgbaToRgb->SetComponents(0,1,2); std::ostringstream ostxx; ostxx.setf(ios::fixed,ios::floatfield); ostxx.precision(5); timer->StopTimer(); ostxx << "root0_" << vtkTimerLog::GetUniversalTime() << "_.png"; vtkStdString *sssxx=new vtkStdString; (*sssxx)=ostxx.str(); writer=vtkPNGWriter::New(); writer->SetFileName(*sssxx); delete sssxx; writer->SetInputConnection(converter->GetOutputPort()); converter->Delete(); importer->Delete(); // rgbaToRgb->Delete(); cout << "Writing " << writer->GetFileName() << endl; writer->Write(); cout << "Wrote " << writer->GetFileName() << endl; // sleep(30); writer->Delete(); #endif // #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG // 1. figure out the back to front ordering vtkCamera *c=r->GetActiveCamera(); vtkIntArray *frontToBackList=vtkIntArray::New(); if(c->GetParallelProjection()) { this->Kdtree->ViewOrderAllProcessesInDirection( c->GetDirectionOfProjection(),frontToBackList); } else { this->Kdtree->ViewOrderAllProcessesFromPosition( c->GetPosition(),frontToBackList); } assert("check same_size" && frontToBackList->GetNumberOfTuples()==numProcs); #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG int i=0; while(iSetFileName(*sssy); delete sssy; writer->SetInputConnection(converter->GetOutputPort()); converter->Delete(); importer->Delete(); // rgbaToRgb->Delete(); cout << "Writing " << writer->GetFileName() << endl; writer->Write(); cout << "Wrote " << writer->GetFileName() << endl; // sleep(30); writer->Delete(); #endif // root node Done. } else { // satellite // send rgba-buffer // framebuffer to PBO. this->PBO->Allocate( VTK_FLOAT, numTups, numComps, vtkPixelBufferObject::PACKED_BUFFER); this->PBO->Bind(vtkPixelBufferObject::PACKED_BUFFER); glReadPixels(0,0,w,h,GL_RGBA,GL_FLOAT, static_cast(nullptr)); // PBO to client glPixelStorei(GL_PACK_ALIGNMENT,1);// server to client this->PBO->Download2D(VTK_FLOAT,this->RawRGBABuffer,dims,4,continuousInc); this->PBO->UnBind(); #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG importer=vtkImageImport::New(); importer->CopyImportVoidPointer(this->RawRGBABuffer, static_cast(byteSize)); importer->SetDataScalarTypeToFloat(); importer->SetNumberOfScalarComponents(4); importer->SetWholeExtent(0,w-1,0,h-1,0,0); importer->SetDataExtentToWholeExtent(); importer->Update(); converter=vtkImageShiftScale::New(); converter->SetInputConnection(importer->GetOutputPort()); converter->SetOutputScalarTypeToUnsignedChar(); converter->SetShift(0.0); converter->SetScale(255.0); // vtkImageExtractComponents *rgbaToRgb=vtkImageExtractComponents::New(); // rgbaToRgb->SetInputConnection(importer->GetOutputPort()); // rgbaToRgb->SetComponents(0,1,2); std::ostringstream ostxx; ostxx.setf(ios::fixed,ios::floatfield); ostxx.precision(5); timer->StopTimer(); ostxx << "satellite_send_" << vtkTimerLog::GetUniversalTime() << "_.png"; vtkStdString *sssxx=new vtkStdString; (*sssxx)=ostxx.str(); writer=vtkPNGWriter::New(); writer->SetFileName(*sssxx); delete sssxx; writer->SetInputConnection(converter->GetOutputPort()); converter->Delete(); importer->Delete(); // rgbaToRgb->Delete(); cout << "Writing " << writer->GetFileName() << endl; writer->Write(); cout << "Wrote " << writer->GetFileName() << endl; // sleep(30); writer->Delete(); #endif // client to root process this->Controller->Send(this->RawRGBABuffer, static_cast(this->RawRGBABufferSize),0, VTK_COMPOSITE_RGBA_PASS_MESSAGE_GATHER); } #ifdef VTK_COMPOSITE_RGBAPASS_DEBUG delete state; timer->Delete(); #endif } // ---------------------------------------------------------------------------- // Description: // Release graphics resources and ask components to release their own // resources. // \pre w_exists: w!=0 void vtkCompositeRGBAPass::ReleaseGraphicsResources(vtkWindow *w) { assert("pre: w_exists" && w!=nullptr); (void)w; if(this->PBO!=nullptr) { this->PBO->Delete(); this->PBO=nullptr; } if(this->RGBATexture!=nullptr) { this->RGBATexture->Delete(); this->RGBATexture=nullptr; } if(this->RootTexture!=nullptr) { this->RootTexture->Delete(); this->RootTexture=nullptr; } }