Reapply r1951.



git-svn-id: http://skia.googlecode.com/svn/trunk@1959 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 09b337c..eae2019 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -658,12 +658,152 @@
         viewport.fWidth  = desc.fWidth;
         viewport.fHeight = desc.fHeight;
 
-        return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
-                                    kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
-                                    viewport, NULL);
+        bool isMSAA = kIsMultisampled_GrPlatformRenderTargetFlagBit &
+                     desc.fRenderTargetFlags;
+
+        return new GrGLRenderTarget(this, rtIDs, NULL, desc.fConfig,
+                                    desc.fStencilBits, isMSAA, viewport, NULL);
     }
 }
 
+namespace {
+
+static const GrGLenum kUnknownGLFormat = ~0;
+
+GrGLenum get_fbo_color_format() {
+    GrGLint cbType;
+    GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                                    GR_GL_COLOR_ATTACHMENT0,
+                                    GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+                                    &cbType);
+    GrGLint cbID;
+    GrGLint cbFormat;
+    switch (cbType) {
+        case GR_GL_RENDERBUFFER:
+            GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                                    GR_GL_COLOR_ATTACHMENT0,
+                                    GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+                                    &cbID);
+            GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER, cbID));
+            GR_GL_GetRenderbufferParameteriv(GR_GL_RENDERBUFFER,
+                                             GR_GL_RENDERBUFFER_INTERNAL_FORMAT,
+                                             &cbFormat);
+            return cbFormat;
+            break;
+        case GR_GL_TEXTURE:
+            // ES doesn't have glGetTexLevelParameter
+            if (GR_GL_SUPPORT_DESKTOP) {
+                GrGLint cbLevel;
+                GrGLint cbFace;
+                GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                                    GR_GL_COLOR_ATTACHMENT0,
+                                    GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+                                    &cbID);
+                GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                                    GR_GL_COLOR_ATTACHMENT0,
+                                    GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
+                                    &cbLevel);
+                GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                            GR_GL_COLOR_ATTACHMENT0,
+                            GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
+                            &cbFace);
+                GrGLenum bind;
+                GrGLenum target;
+                if (cbFace) {
+                    bind = GR_GL_TEXTURE_CUBE_MAP;
+                    target = cbFace;
+                } else {
+                    bind = GR_GL_TEXTURE_2D;
+                    target = GR_GL_TEXTURE_2D;
+                }
+                GR_GL(BindTexture(bind, cbID));
+                GR_GL_GetTexLevelParameteriv(target, cbLevel, 
+                                    GR_GL_TEXTURE_INTERNAL_FORMAT, &cbFormat);
+                return cbFormat;
+            } else {
+                return kUnknownGLFormat;
+            }
+            break;
+        default:
+            // we can get here with FBO 0, not a render buffer or a texture
+            return kUnknownGLFormat;
+    }
+}
+
+GrPixelConfig internal_color_format_to_config(GrGLenum iFormat) {
+    switch (iFormat) {
+        case GR_GL_RGB565:
+            return kRGB_565_GrPixelConfig;
+        case GR_GL_RGBA4:
+            return kRGBA_4444_GrPixelConfig;
+        case GR_GL_RGBA8:
+        case GR_GL_SRGB8_ALPHA8:
+        case GR_GL_SRGB_ALPHA:
+        case GR_GL_RGBA:
+        case GR_GL_BGRA:
+            return kRGBA_8888_GrPixelConfig;
+        case GR_GL_RGB8:
+        case GR_GL_SRGB8:
+        case GR_GL_SRGB:
+            return kRGBX_8888_GrPixelConfig;
+        default:
+            // there are many GL formats we don't have enums
+            // for. We should still render to them if the client
+            // asks us.
+            return kUnknown_GrPixelConfig;
+    }
+}
+
+GrPixelConfig get_implied_color_config(bool arbFBOExtension) {
+    GrGLint rSize, bSize, gSize, aSize;
+    if (arbFBOExtension) {
+        GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER, 
+                GR_GL_COLOR_ATTACHMENT0,
+                GR_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &rSize);
+        GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                GR_GL_COLOR_ATTACHMENT0,
+                GR_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &gSize);
+        GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER, 
+                GR_GL_COLOR_ATTACHMENT0,
+                GR_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &bSize);
+        GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                GR_GL_COLOR_ATTACHMENT0, 
+                GR_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &aSize);
+    } else {
+        GR_GL_GetIntegerv(GR_GL_RED_BITS, &rSize);
+        GR_GL_GetIntegerv(GR_GL_GREEN_BITS, &gSize);
+        GR_GL_GetIntegerv(GR_GL_BLUE_BITS, &bSize);
+        GR_GL_GetIntegerv(GR_GL_ALPHA_BITS, &aSize);
+    }
+
+    if(8 == rSize && 8 == gSize && 8 == bSize) {
+       if (0 == aSize) {
+           return kRGBX_8888_GrPixelConfig;
+       } else if (8 == aSize) {
+           return kRGBA_8888_GrPixelConfig;
+       }
+    } else if (4 == rSize && 4 == gSize && 4 == bSize && 4 == aSize) {
+        return kRGBA_4444_GrPixelConfig;
+    } else if (5 == rSize && 6 == gSize && 5 == bSize && 0 == aSize) {
+        return kRGB_565_GrPixelConfig;
+    }
+    return kUnknown_GrPixelConfig;
+}
+
+int get_fbo_stencil_bits(bool arbFBOExtension) {
+    GrGLint stencilBits;
+    if (arbFBOExtension) {
+        GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
+                                    GR_GL_STENCIL_ATTACHMENT,
+                                    GR_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+                                    &stencilBits);
+    } else {
+        GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, &stencilBits);
+    }
+    return stencilBits;
+}
+}
+
 GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
 
     GrGLRenderTarget::GLRenderTargetIDs rtIDs;
@@ -673,17 +813,29 @@
     rtIDs.fMSColorRenderbufferID = 0;
     rtIDs.fStencilRenderbufferID = 0;
 
+    bool arbFBO = (GR_GL_SUPPORT_DESKTOP && (fGLVersion > 3.0 ||
+                   this->hasExtension("GL_ARB_framebuffer_object")));
+
     GrGLIRect viewport;
     viewport.setFromGLViewport();
-    GrGLuint stencilBits;
-    GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
+    int stencilBits = get_fbo_stencil_bits(arbFBO);
 
+    GrPixelConfig config;
     GrGLint samples;
     GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
+    GrGLenum fmat = get_fbo_color_format();
+    if (kUnknownGLFormat == fmat) {
+        config = get_implied_color_config(arbFBO);
+    } else {
+        config = internal_color_format_to_config(fmat);
+    }
+
+    // may have to bind a texture to gets its format
+    this->setSpareTextureUnit();
 
     rtIDs.fOwnIDs = false;
 
-    return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, 
+    return new GrGLRenderTarget(this, rtIDs, NULL, config, stencilBits,
                                 (samples > 0), viewport, NULL);
 }