summaryrefslogtreecommitdiff
path: root/src/OffscreenContextAll.hpp
blob: 1c73b737a6c35a06ab911d3e87b317e8db2937a7 (plain)
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
// Functions shared by OffscreenContext[platform].cc (or .mm)
// #include directly after definition of struct OffscreenContext.

void bind_offscreen_context(OffscreenContext *ctx)
{
  if (ctx) fbo_bind(ctx->fbo);
}

/*
  Capture framebuffer from OpenGL and write it to the given filename as PNG.
*/
bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
  std::ofstream fstream(filename);
  if (!fstream.is_open()) {
    std::cerr << "Can't open file " << filename << " for writing";
    return false;
  } else {
    save_framebuffer(ctx, fstream);
    fstream.close();
  }
  return true;
}

/*!
  Capture framebuffer from OpenGL and write it to the given ostream.
	Called by save_framebuffer() from platform-specific code.
*/
bool save_framebuffer_common(OffscreenContext *ctx, std::ostream &output)
{
  if (!ctx) return false;
  int samplesPerPixel = 4; // R, G, B and A
  vector<GLubyte> pixels(ctx->width * ctx->height * samplesPerPixel);
  glReadPixels(0, 0, ctx->width, ctx->height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);

  // Flip it vertically - images read from OpenGL buffers are upside-down
  int rowBytes = samplesPerPixel * ctx->width;

  unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height);
  if (!flippedBuffer) {
    std::cerr << "Unable to allocate flipped buffer for corrected image.";
    return 1;
  }
  flip_image(&pixels[0], flippedBuffer, samplesPerPixel, ctx->width, ctx->height);

  bool writeok = write_png(output, flippedBuffer, ctx->width, ctx->height);

  free(flippedBuffer);

	return writeok;
}

//	Called by create_offscreen_context() from platform-specific code.
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) {
    cerr << "Unable to init GLEW: " << glewGetErrorString(err) << "\n";
    return NULL;
  }
  //cerr << glew_dump(0);

  ctx->fbo = fbo_new();
  if (!fbo_init(ctx->fbo, ctx->width, ctx->height)) {
    return NULL;
  }

  return ctx;
}

contact: Jan Huwald // Impressum