src/gl/OffscreenContextAll.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    
    // Functions shared by OffscreenContext[platform].cc
    // #include this directly after definition of struct OffscreenContext.
    
    /*!
      Capture framebuffer from OpenGL and write it to the given ostream.
      Called by save_framebuffer() from platform-specific code.
    */
    static bool save_framebuffer_common(OffscreenContext *ctx, FILE * output)
    {
      if (!ctx) return false;
      int samplesPerPixel = 3; // R, G, B
      unsigned char pixels[ctx->width*ctx->height*samplesPerPixel];
      glReadPixels (0, 0, ctx->width, ctx->height,
    		GL_RGB, GL_UNSIGNED_BYTE, pixels);
      fprintf (output, "P6 %d %d 255\n", ctx->width, ctx->height);
      fwrite (pixels, sizeof(unsigned char),
    	  ctx->width*ctx->height*samplesPerPixel, output);
      return true;
    }
    
    //	Called by get_framebuffer_pixels() from platform-specific code.
    static unsigned char * get_framebuffer_pixels_common (OffscreenContext *ctx)
    {
      if (!ctx) return NULL;
      glReadPixels (0, 0, ctx->width, ctx->height,
    		GL_RGBA, GL_UNSIGNED_BYTE, ctx->image);
      return ctx->image;
    }
    
    //	Called by get_framebuffer_depth() from platform-specific code.
    static unsigned int * get_framebuffer_depth_common (OffscreenContext *ctx)
    {
      if (!ctx) return NULL;
    
      if (!ctx->depth) {
        ctx->depth = malloc (sizeof(unsigned int)*ctx->width*ctx->height);
        glGenTextures (1, &ctx->depth_texture);
        glBindTexture (GL_TEXTURE_2D, ctx->depth_texture);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
    		  ctx->width, ctx->height,
    		  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
      }
    
      glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 0, 0, ctx->width, ctx->height);
      glGetTexImage (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
    		 ctx->depth);
    
      return ctx->depth;
    }
    
    //	Called by create_offscreen_context() from platform-specific code.
    static OffscreenContext *create_offscreen_context_common(OffscreenContext *ctx)
    {
      if (!ctx) return NULL;
      GLenum err = glewInit(); // must come after Context creation and before FBO c$
      if (GLEW_OK != err) {
        fprintf (stderr, "Unable to init GLEW: %s\n", glewGetErrorString(err));
        return NULL;
      }
    
      ctx->fbo = fbo_new();
      if (!fbo_init(ctx->fbo, ctx->width, ctx->height)) {
        return NULL;
      }
    
      ctx->image = malloc (sizeof(unsigned char)*ctx->width*ctx->height*4);
      ctx->depth = NULL;
    
      return ctx;
    }
    
    //	Called by teardown_offscreen_context() from platform-specific code.
    static bool teardown_offscreen_context_common(OffscreenContext *ctx)
    {
      if (!ctx) return false;
      free (ctx->image);
      if (ctx->depth) {
        glDeleteTextures (1, &ctx->depth_texture);
        free (ctx->depth);
      }
      return true;
    }