void PrintAudioStreamInfo(const AAudioStream * stream) { #define STREAM_CALL(c) AAudioStream_##c((AAudioStream*)stream) LOGI("StreamID: %p", stream); LOGI("BufferCapacity: %d", STREAM_CALL(getBufferCapacityInFrames)); LOGI("BufferSize: %d", STREAM_CALL(getBufferSizeInFrames)); LOGI("FramesPerBurst: %d", STREAM_CALL(getFramesPerBurst)); LOGI("XRunCount: %d", STREAM_CALL(getXRunCount)); LOGI("SampleRate: %d", STREAM_CALL(getSampleRate)); LOGI("SamplesPerFrame: %d", STREAM_CALL(getChannelCount)); LOGI("DeviceId: %d", STREAM_CALL(getDeviceId)); LOGI("Format: %s", FormatToString(STREAM_CALL(getFormat))); LOGI("SharingMode: %s", (STREAM_CALL(getSharingMode)) == AAUDIO_SHARING_MODE_EXCLUSIVE ? "EXCLUSIVE" : "SHARED"); aaudio_performance_mode_t perfMode = STREAM_CALL(getPerformanceMode); std::string perfModeDescription; switch (perfMode){ case AAUDIO_PERFORMANCE_MODE_NONE: perfModeDescription = "NONE"; break; case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: perfModeDescription = "LOW_LATENCY"; break; case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: perfModeDescription = "POWER_SAVING"; break; default: perfModeDescription = "UNKNOWN"; break; } LOGI("PerformanceMode: %s", perfModeDescription.c_str()); aaudio_direction_t dir = STREAM_CALL(getDirection); LOGI("Direction: %s", (dir == AAUDIO_DIRECTION_OUTPUT ? "OUTPUT" : "INPUT")); if (dir == AAUDIO_DIRECTION_OUTPUT) { LOGI("FramesReadByDevice: %d", (int32_t)STREAM_CALL(getFramesRead)); LOGI("FramesWriteByApp: %d", (int32_t)STREAM_CALL(getFramesWritten)); } else { LOGI("FramesReadByApp: %d", (int32_t)STREAM_CALL(getFramesRead)); LOGI("FramesWriteByDevice: %d", (int32_t)STREAM_CALL(getFramesWritten)); } #undef STREAM_CALL }
void FBOBJECT::Init(GLSTATEMANAGER & glstate, std::vector <FBTEXTURE*> newtextures, std::ostream & error_output, bool force_multisample_off) { OPENGL_UTILITY::CheckForOpenGLErrors("FBO init start", error_output); const bool verbose = false; if (inited) { if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl; DeInit(); OPENGL_UTILITY::CheckForOpenGLErrors("FBO deinit", error_output); } textures = newtextures; inited = true; assert(!textures.empty()); // run some sanity checks and find out which textures are for the color attachment and // which are for the depth attachment std::vector <FBTEXTURE*> color_textures; std::vector <FBTEXTURE*> depth_textures; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if ((*i)->texture_format == FBTEXTURE::DEPTH24) depth_textures.push_back(*i); else color_textures.push_back(*i); //assert(!(*i)->attached || (force_multisample_off && (*i)->renderbuffer_multisample != 0)); (*i)->attached = true; } if (verbose) error_output << "INFO: color textures: " << color_textures.size() << ", depth textures: " << depth_textures.size() << std::endl; //need at least some textures assert(color_textures.size() + depth_textures.size() >= 1); //can't have more than one depth attachment assert(depth_textures.size() < 2); //can't have more than 4 color textures assert(color_textures.size() < 5); for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { if (verbose) error_output << "INFO: found cubemap" << std::endl; //can't have MRT with cubemaps assert(color_textures.size() == 1); //can't have multisample with cubemaps assert((*i)->multisample == 0); //can't have depth texture with cubemaps assert(depth_textures.empty()); } } //find what multisample value to use int multisample = 0; if (!color_textures.empty()) { multisample = -1; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if (multisample == -1) multisample = (*i)->multisample; //all must have the same multisample assert(multisample == (*i)->multisample); } } if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl; if (force_multisample_off) multisample = 0; //either we have no multisample //or multisample and no depth texture assert((multisample == 0) || ((multisample > 0) && depth_textures.empty())); //ensure consistent sizes width = -1; height = -1; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if (width == -1) width = (*i)->sizew; if (height == -1) height = (*i)->sizeh; assert(width == (*i)->sizew); assert(height == (*i)->sizeh); } if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl; //initialize framebuffer object (FBO) assert(GLEW_ARB_framebuffer_object); glGenFramebuffers(1, &framebuffer_object); if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO generation", error_output); //bind the framebuffer glstate.BindFramebuffer(framebuffer_object); OPENGL_UTILITY::CheckForOpenGLErrors("FBO binding", error_output); //initialize renderbuffer object that's used for our depth buffer if we're not using //a depth texture if (depth_textures.empty()) { glGenRenderbuffers(1, &renderbuffer_depth); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_depth); if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer generation", error_output); if (multisample > 0) { // need a separate multisample depth buffer glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height); if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl; } else glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer initialization", error_output); //attach the render buffer to the FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_depth); if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer attachment", error_output); } GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE}; { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { buffers[count] = GL_COLOR_ATTACHMENT0+count; } } glDrawBuffers(4, buffers); glReadBuffer(buffers[0]); if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl; if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO buffer mask set", error_output); //add separate multisample color buffers for each color texture if (multisample > 0) { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { // need a separate multisample color buffer glGenRenderbuffers(1, &(*i)->renderbuffer_multisample); glBindRenderbuffer(GL_RENDERBUFFER, (*i)->renderbuffer_multisample); glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, (*i)->texture_format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+count, GL_RENDERBUFFER, (*i)->renderbuffer_multisample); if (verbose) error_output << "INFO: generating separate multisample color buffer " << count << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output); } } //attach any color textures to the FBO { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { int texture_attachment = GL_COLOR_ATTACHMENT0+count; if (multisample == 0) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, (*i)->texture_target, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl; } (*i)->texture_attachment = texture_attachment; } } } //attach the depth texture to the FBO, if there is one { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = depth_textures.begin(); i != depth_textures.end(); i++,count++) { if (multisample == 0) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching cubemap depth texture" << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (*i)->texture_target, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching depth texture" << std::endl; } } } } OPENGL_UTILITY::CheckForOpenGLErrors("FBO attachment", error_output); bool status_ok = CheckStatus(error_output); if (!status_ok) { error_output << "Error initializing FBO:" << std::endl; int count = 0; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { error_output << "\t" << count << ". " << TargetToString((*i)->texture_target) << ": " << FormatToString((*i)->texture_format) << std::endl; count++; } } assert(status_ok); glstate.BindFramebuffer(0); OPENGL_UTILITY::CheckForOpenGLErrors("FBO unbinding", error_output); // if multisampling is on, create another framebuffer object for the single sample version of these textures if (multisample > 0) { if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl; assert(multisample_dest_singlesample_framebuffer_object.empty()); multisample_dest_singlesample_framebuffer_object.push_back(FBOBJECT()); multisample_dest_singlesample_framebuffer_object.back().Init(glstate, newtextures, error_output, true); } }
void FrameBufferObject::Init( GraphicsState & glstate, const std::vector <FrameBufferTexture*> & newtextures, std::ostream & error_output, bool force_multisample_off) { CheckForOpenGLErrors("FBO init start", error_output); const bool verbose = false; if (inited) { if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl; DeInit(); CheckForOpenGLErrors("FBO deinit", error_output); } inited = true; // need at least some textures assert(!newtextures.empty()); textures = newtextures; width = -1; height = -1; std::vector <FrameBufferTexture*> color_textures; FrameBufferTexture * depth_texture = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { // ensure consistent sizes if (width == -1) width = (*i)->GetW(); if (height == -1) height = (*i)->GetH(); assert(width == int((*i)->GetW())); assert(height == int((*i)->GetH())); // separate textures by type if ((*i)->GetFormat() == FrameBufferTexture::DEPTH24) { // can't have more than one depth attachment assert(!depth_texture); depth_texture = *i; } else { color_textures.push_back(*i); } } if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl; if (verbose) error_output << "INFO: color textures: " << color_textures.size() << std::endl; if (verbose && depth_texture) error_output << "INFO: depth texture: 1" << std::endl; // can't have more than 4 color attachments assert(color_textures.size() < 5); // check for cubemaps for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++) { if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP) { if (verbose) error_output << "INFO: found cubemap" << std::endl; // can't have MRT with cubemaps assert(color_textures.size() == 1); // can't have multisample with cubemaps assert((*i)->GetMultiSample() == 0); // can't have depth texture with cubemaps assert(!depth_texture); } } // find what multisample value to use int multisample = 0; if (!color_textures.empty()) { multisample = -1; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { if (multisample == -1) multisample = (*i)->GetMultiSample(); // all must have the same multisample assert(multisample == (*i)->GetMultiSample()); } } if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl; if (force_multisample_off) multisample = 0; // either we have no multisample or multisample and no depth texture assert((multisample == 0) || ((multisample > 0) && depth_texture)); // initialize framebuffer object glGenFramebuffers(1, &framebuffer_object); if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl; CheckForOpenGLErrors("FBO generation", error_output); // bind framebuffer glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object); CheckForOpenGLErrors("FBO binding", error_output); if (!depth_texture) { // create depth render buffer if we're not using a depth texture glGenRenderbuffers(1, &depth_renderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer); if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl; CheckForOpenGLErrors("FBO renderbuffer generation", error_output); if (multisample > 0) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height); if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl; } else { glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); } CheckForOpenGLErrors("FBO renderbuffer initialization", error_output); // attach depth render buffer to the FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_renderbuffer); if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl; CheckForOpenGLErrors("FBO renderbuffer attachment", error_output); } if (multisample > 0) { // create/attach separate multisample color buffers for each color texture multisample_renderbuffers.resize(color_textures.size(), 0); for (size_t i = 0; i < color_textures.size(); i++) { glGenRenderbuffers(1, &multisample_renderbuffers[i]); glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffers[i]); glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, color_textures[i]->GetFormat(), width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, multisample_renderbuffers[i]); if (verbose) error_output << "INFO: generating separate multisample color buffer " << i << std::endl; CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output); } } else { // attach color textures to frame buffer object int count = 0; for (std::vector <FrameBufferTexture*>::iterator i = color_textures.begin(); i != color_textures.end(); i++, count++) { int attachment = GL_COLOR_ATTACHMENT0 + count; if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->GetId(), 0); if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, (*i)->GetTarget(), (*i)->GetId(), 0); if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl; } (*i)->SetAttachment(attachment); CheckForOpenGLErrors("FBO attachment", error_output); } if (depth_texture) { // attach depth texture to frame buffer object glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture->GetTarget(), depth_texture->GetId(), 0); depth_texture->SetAttachment(GL_DEPTH_ATTACHMENT); if (verbose) error_output << "INFO: attaching depth texture" << std::endl; CheckForOpenGLErrors("FBO attachment", error_output); } } GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE}; { int count = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++, count++) { buffers[count] = GL_COLOR_ATTACHMENT0 + count; } glDrawBuffers(count, buffers); glReadBuffer(buffers[0]); CheckForOpenGLErrors("FBO buffer mask set", error_output); } if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl; if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl; if (!CheckStatus(error_output)) { error_output << "Error initializing FBO:" << std::endl; int count = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { error_output << "\t" << count << ". " << TargetToString(FrameBufferTexture::Target((*i)->GetTarget())); error_output << ": " << FormatToString((*i)->GetFormat()) << std::endl; count++; } assert(0); } // explicitely unbind framebuffer object glstate.BindFramebuffer(GL_FRAMEBUFFER, 0); CheckForOpenGLErrors("FBO unbinding", error_output); // if multisampling is on, create another framebuffer object for the single sample version of these textures if (multisample > 0) { if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl; assert(!singlesample_framebuffer_object); singlesample_framebuffer_object = new FrameBufferObject(); singlesample_framebuffer_object->Init(glstate, newtextures, error_output, true); } }