/*========================================================================= Program: Visualization Toolkit Module: vtkOpenGLContextBufferId.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 "vtkOpenGLContextBufferId.h" #include "vtkIntArray.h" #include "vtkObjectFactory.h" #include "vtkOpenGLError.h" #include "vtkOpenGLRenderWindow.h" #include "vtkOpenGLState.h" #include "vtkOpenGLTexture.h" #include "vtkTextureObject.h" #include vtkStandardNewMacro(vtkOpenGLContextBufferId); //------------------------------------------------------------------------------ vtkOpenGLContextBufferId::vtkOpenGLContextBufferId() { this->Texture = nullptr; this->Context = nullptr; } //------------------------------------------------------------------------------ vtkOpenGLContextBufferId::~vtkOpenGLContextBufferId() { if (this->Texture != nullptr) { vtkErrorMacro("texture should have been released."); } } //------------------------------------------------------------------------------ void vtkOpenGLContextBufferId::ReleaseGraphicsResources() { if (this->Texture != nullptr) { this->Texture->Delete(); this->Texture = nullptr; } } //------------------------------------------------------------------------------ void vtkOpenGLContextBufferId::SetContext(vtkRenderWindow* context) { vtkOpenGLRenderWindow* c = vtkOpenGLRenderWindow::SafeDownCast(context); if (this->Context != c) { this->ReleaseGraphicsResources(); this->Context = c; this->Modified(); } } //------------------------------------------------------------------------------ vtkRenderWindow* vtkOpenGLContextBufferId::GetContext() { return this->Context; } //------------------------------------------------------------------------------ bool vtkOpenGLContextBufferId::IsSupported() { assert("pre: context_is_set" && this->GetContext() != nullptr); return vtkTextureObject::IsSupported(this->Context); } //------------------------------------------------------------------------------ void vtkOpenGLContextBufferId::Allocate() { assert("pre: positive_width" && this->GetWidth() > 0); assert("pre: positive_height" && this->GetHeight() > 0); assert("pre: context_is_set" && this->GetContext() != nullptr); if (this->Texture == nullptr) { this->Texture = vtkTextureObject::New(); this->Texture->SetContext(this->Context); } this->Context->MakeCurrent(); // 3: RGB this->Texture->Allocate2D(static_cast(this->GetWidth()), static_cast(this->GetHeight()), 3, VTK_UNSIGNED_CHAR); } //------------------------------------------------------------------------------ bool vtkOpenGLContextBufferId::IsAllocated() const { return this->Texture != nullptr && this->Texture->GetWidth() == static_cast(this->Width) && this->Texture->GetHeight() == static_cast(this->Height); } //------------------------------------------------------------------------------ void vtkOpenGLContextBufferId::SetValues(int srcXmin, int srcYmin) { assert("pre: is_allocated" && this->IsAllocated()); // copy the current read buffer to the texture. this->Texture->CopyFromFrameBuffer(srcXmin, srcYmin, 0, 0, this->Width, this->Height); } //------------------------------------------------------------------------------ vtkIdType vtkOpenGLContextBufferId::GetPickedItem(int x, int y) { assert("pre: is_allocated" && this->IsAllocated()); vtkOpenGLClearErrorMacro(); vtkIdType result = -1; if (x < 0 || x >= this->Width) { vtkDebugMacro(<< "x mouse position out of range: x=" << x << " (width=" << this->Width << ")"); } else { if (y < 0 || y >= this->Height) { vtkDebugMacro(<< "y mouse position out of range: y=" << y << " (height=" << this->Height << ")"); } else { this->Context->MakeCurrent(); vtkOpenGLState* ostate = this->Context->GetState(); // Render texture to current write buffer. Texel x,y is rendered at // pixel x,y (instead of pixel 0,0 to work around pixel ownership test). GLint savedDrawBuffer; glGetIntegerv(GL_DRAW_BUFFER, &savedDrawBuffer); vtkOpenGLState::ScopedglEnableDisable dsaver(ostate, GL_DEPTH_TEST); vtkOpenGLState::ScopedglEnableDisable ssaver(ostate, GL_STENCIL_TEST); vtkOpenGLState::ScopedglEnableDisable bsaver(ostate, GL_BLEND); if (savedDrawBuffer != GL_BACK_LEFT) { ostate->vtkglDrawBuffer(GL_BACK_LEFT); } ostate->vtkglDisable(GL_DEPTH_TEST); ostate->vtkglDisable(GL_STENCIL_TEST); ostate->vtkglDisable(GL_BLEND); this->Texture->CopyToFrameBuffer(x, y, x, y, x, y, this->Context->GetSize()[0], this->Context->GetSize()[1], nullptr, nullptr); GLint savedReadBuffer; glGetIntegerv(GL_READ_BUFFER, &savedReadBuffer); ostate->vtkglReadBuffer(GL_BACK_LEFT); // To workaround pixel ownership test, // get value from current read buffer at pixel (x,y) instead of just // (0,0). ostate->vtkglPixelStorei(GL_PACK_ALIGNMENT, 1); unsigned char rgb[3]; rgb[0] = 5; rgb[1] = 1; rgb[2] = 8; glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb); if (savedReadBuffer != GL_BACK_LEFT) { ostate->vtkglReadBuffer(static_cast(savedReadBuffer)); } if (savedDrawBuffer != GL_BACK_LEFT) { ostate->vtkglDrawBuffer(static_cast(savedDrawBuffer)); } int value = (static_cast(rgb[0]) << 16) | (static_cast(rgb[1]) << 8) | static_cast(rgb[2]); result = static_cast(value - 1); } } assert("post: valid_result" && result >= -1); vtkOpenGLCheckErrorMacro("failed after GetPickedItem"); return result; } //------------------------------------------------------------------------------ void vtkOpenGLContextBufferId::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }