00001
00032 #include "linden_common.h"
00033
00034 #include "llrendertarget.h"
00035 #include "llglimmediate.h"
00036 #include "llgl.h"
00037
00038
00039 BOOL LLRenderTarget::sUseFBO = FALSE;
00040
00041 LLRenderTarget::LLRenderTarget() :
00042 mResX(0),
00043 mResY(0),
00044 mTex(0),
00045 mFBO(0),
00046 mDepth(0),
00047 mStencil(0),
00048 mUseDepth(FALSE),
00049 mRenderDepth(FALSE),
00050 mUsage(GL_TEXTURE_2D)
00051 {
00052 }
00053
00054 LLRenderTarget::~LLRenderTarget()
00055 {
00056 release();
00057 }
00058
00059 void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL use_fbo)
00060 {
00061 stop_glerror();
00062 mResX = resx;
00063 mResY = resy;
00064
00065 mUsage = usage;
00066 mUseDepth = depth;
00067 release();
00068
00069 glGenTextures(1, (GLuint *) &mTex);
00070 glBindTexture(mUsage, mTex);
00071 glTexImage2D(mUsage, 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL);
00072
00073 glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00074 glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00075
00076 if (mUsage != GL_TEXTURE_RECTANGLE_ARB)
00077 {
00078 glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
00079 glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
00080 }
00081 else
00082 {
00083
00084 glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00085 glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00086 }
00087
00088 stop_glerror();
00089
00090 if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
00091 {
00092
00093 if (depth)
00094 {
00095 stop_glerror();
00096 allocateDepth();
00097 stop_glerror();
00098 }
00099
00100 glGenFramebuffersEXT(1, (GLuint *) &mFBO);
00101
00102 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
00103
00104 if (mDepth)
00105 {
00106 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, mUsage, mDepth, 0);
00107 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, mUsage, mDepth, 0);
00108 stop_glerror();
00109 }
00110
00111 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
00112 mUsage, mTex, 0);
00113 stop_glerror();
00114
00115 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00116 stop_glerror();
00117 }
00118 }
00119
00120 void LLRenderTarget::allocateDepth()
00121 {
00122 glGenTextures(1, (GLuint *) &mDepth);
00123 glBindTexture(mUsage, mDepth);
00124 glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00125 glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00126 glTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
00127 }
00128
00129 void LLRenderTarget::release()
00130 {
00131 if (mFBO)
00132 {
00133 glDeleteFramebuffersEXT(1, (GLuint *) &mFBO);
00134 mFBO = 0;
00135 }
00136
00137 if (mTex)
00138 {
00139 glDeleteTextures(1, (GLuint *) &mTex);
00140 mTex = 0;
00141 }
00142
00143 if (mDepth)
00144 {
00145 glDeleteTextures(1, (GLuint *) &mDepth);
00146 mDepth = 0;
00147 }
00148 }
00149
00150 void LLRenderTarget::bindTarget()
00151 {
00152 if (mFBO)
00153 {
00154 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
00155 }
00156
00157 glViewport(0, 0, mResX, mResY);
00158 }
00159
00160
00161 void LLRenderTarget::unbindTarget()
00162 {
00163 if (gGLManager.mHasFramebufferObject)
00164 {
00165 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00166 }
00167 }
00168
00169 void LLRenderTarget::clear()
00170 {
00171 U32 mask = GL_COLOR_BUFFER_BIT;
00172 if (mUseDepth)
00173 {
00174 mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
00175 }
00176 if (mFBO)
00177 {
00178 glClear(mask);
00179 }
00180 else
00181 {
00182 LLGLEnable scissor(GL_SCISSOR_TEST);
00183 glScissor(0, 0, mResX, mResY);
00184 glClear(mask);
00185 }
00186 }
00187
00188 void LLRenderTarget::bindTexture()
00189 {
00190 glBindTexture(mUsage, mTex);
00191 }
00192
00193 void LLRenderTarget::bindDepth()
00194 {
00195 glBindTexture(mUsage, mDepth);
00196 }
00197
00198
00199 void LLRenderTarget::flush(BOOL fetch_depth)
00200 {
00201 gGL.flush();
00202 if (!mFBO)
00203 {
00204 bindTexture();
00205 glCopyTexSubImage2D(mUsage, 0, 0, 0, 0, 0, mResX, mResY);
00206
00207 if (fetch_depth)
00208 {
00209 if (!mDepth)
00210 {
00211 allocateDepth();
00212 }
00213
00214 bindDepth();
00215 glCopyTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
00216 }
00217 }
00218 else
00219 {
00220 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00221 }
00222 }
00223
00224 BOOL LLRenderTarget::isComplete() const
00225 {
00226 return (mTex || mDepth) ? TRUE : FALSE;
00227 }
00228
00229 void LLRenderTarget::getViewport(S32* viewport)
00230 {
00231 viewport[0] = 0;
00232 viewport[1] = 0;
00233 viewport[2] = mResX;
00234 viewport[3] = mResY;
00235 }
00236