# Code examples how to setup Retina

**URL:** <https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349>\
**Category:** support\
**Created:** [April 4, 2023, 12:59pm UTC](https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349 "2023-04-04T12:59:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lefty](https://avatars.discourse-cdn.com/v4/letter/l/85e7bf/32.png) [@lefty](https://discourse.glfw.org/u/lefty)\
**Post date:** [April 4, 2023, 12:59pm UTC](https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349/1 "2023-04-04T12:59:18Z")

</div>

Is there any code examples how to set up a glfw an application to work properly with a retina display?  
It not very clear if GLFW\_COCOA\_RETINA\_FRAMEBUFFER should be used, or if cursor position needs to be scaled, etc. Unfortunately I do not have a retina device to test on, that’s why example code would be helpful

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [April 5, 2023, 11:06am UTC](https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349/2 "2023-04-05T11:06:44Z")

</div>

I don’t have a retina device, but here’s some guidance:

`GLFW_COCOA_RETINA_FRAMEBUFFER` is only required if you don’t want the higher resolution framebuffer. If you have a demanding application which is bound by a performance constraint which scales with resolution this may help, but a better approach which will work across all systems would be to use something like [Dynamic Resolution Rendering](https://www.intel.com/content/www/us/en/developer/articles/technical/dynamic-resolution-rendering-article.html), the basic implementation being pretty simple to set up.

The [Cursor position](https://www.glfw.org/docs/3.3/input_guide.html#cursor_pos) is measured in screen coordinates - i.e. the same ones used to create, resize and position your window. So you don’t need to

Your projection matrix can stay based on the window size in screen coordinates since it is a ratio which projects to clip-space (-1.0 to 1.0 range for each axis). If you do this then you can transform the mouse position to clip-space.

You need to use the framebuffer size for your viewport, clipping, render targets etc. You should use this in the code for every platform.

For rendering text make sure to scale the resolution of the text by the framebuffer to to window size if you keep your text to window size ratio the same.

Hope this helps.

---

<div class="post-metadata">

**Author:** ![lefty](https://avatars.discourse-cdn.com/v4/letter/l/85e7bf/32.png) [@lefty](https://discourse.glfw.org/u/lefty)\
**Post date:** [April 5, 2023, 2:54pm UTC](https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349/3 "2023-04-05T14:54:33Z")

</div>

Thanks for the answer.  
Setting GLFW\_COCOA\_RETINA\_FRAMEBUFFER to false ensures that glfwGetFramebufferSize and glfwGetWindowSize both return the same values, right?

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [April 5, 2023, 3:13pm UTC](https://discourse.glfw.org/t/code-examples-how-to-setup-retina/2349/4 "2023-04-05T15:13:06Z")

</div>

This should be the case, though note that there is a bug posted about this:

> <https://github.com/glfw/glfw/issues/1968>
>
> Test initial result of \`glfwGetFrameBufferSize\` and \`glfwGetWindowContentScale\` …is incorrect on MacOS, when I run on retina display but set \`GLFW\_COCOA\_RETINA\_FRAMEBUFFER\` to \`GLFW\_FALSE\`.
> 
> \`glfwPollEvents()\` will correct that result, but \`framebufferSizeCallback\` is never invoked.
> 
> \### Platform
> 
> \* GLFW version: glfw-3.3.4.bin.MACOS
> \* Compiler: Apple clang version 12.0.0 (clang-1200.0.32.27)
> \* Target: x86\_64-apple-darwin20.5.0
> \* MacOS version: 11.4
> 
> \### Test Source Code
> 
> https://github.com/jmecn/glfw-3.3.4-issue-1968
> 
> \`\`\`\`c
> \#include \<GLFW/glfw3.h\>
> \#include \<stdlib.h\>
> \#include \<stdio.h\>
> \#include \<string.h\>
> 
> void errorCallback(int error, const char\* description) {
> fprintf(stderr, "Error: %s\\n", description);
> }
> 
> void keyCallback(GLFWwindow\* window, int key, int scancode, int action, int mods) {
> if (key == GLFW\_KEY\_ESCAPE && action == GLFW\_PRESS) {
> glfwSetWindowShouldClose(window, GLFW\_TRUE);
> }
> }
> 
> void framebufferSizeCallback(GLFWwindow\* window, int width, int height) {
> printf("callback fbSize=%dx%d\\n", width, height);
> }
> 
> void printFrameBufferSize(GLFWwindow\* window, int frame) {
> int w, h;
> float xscale, yscale;
> glfwGetFramebufferSize(window, &w, &h);
> glfwGetWindowContentScale(window, &xscale, &yscale);
> printf("frame#%d, fbSize=%dx%d, scale=%.2fx%.2f\\n", frame, w, h, xscale, yscale);
> }
> 
> int main(int argc, char const \*argv\[\]) {
> int frame = -2;// two frame before loops
> int useRetinaFrameBuffer = GLFW\_FALSE;
> int isPollEventBeforeLoop = GLFW\_FALSE;
> 
> for (int i = 0; i \< argc; i++) {
> if (strncmp("retina", argv\[i\], 6) == 0) {
> useRetinaFrameBuffer = GLFW\_TRUE;
> }
> if (strncmp("poll", argv\[i\], 4) == 0) {
> isPollEventBeforeLoop = GLFW\_TRUE;
> }
> }
> 
> glfwSetErrorCallback(errorCallback);
> 
> if (!glfwInit()) {
> exit(-1);
> }
> 
> // hint
> glfwWindowHint(GLFW\_CONTEXT\_VERSION\_MAJOR, 3);
> glfwWindowHint(GLFW\_CONTEXT\_VERSION\_MINOR, 2);
> glfwWindowHint(GLFW\_OPENGL\_PROFILE, GLFW\_OPENGL\_CORE\_PROFILE);
> \#ifdef \_\_APPLE\_\_
> glfwWindowHint(GLFW\_OPENGL\_FORWARD\_COMPAT, GLFW\_TRUE);
> \#endif
> glfwWindowHint(GLFW\_COCOA\_RETINA\_FRAMEBUFFER, useRetinaFrameBuffer);
> 
> GLFWwindow\* window = glfwCreateWindow(640, 400, "Test FrameBuffer Size", NULL, NULL);
> if (!window) {
> glfwTerminate();
> exit(-1);
> }
> 
> glfwMakeContextCurrent(window);
> glfwSwapInterval(1);
> glfwSetKeyCallback(window, keyCallback);
> glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
> 
> // loop
> printFrameBufferSize(window, frame++);
> 
> if (isPollEventBeforeLoop) {
> glfwPollEvents();// \<------- this is the point which changed glfwGetFramebufferSize result
> }
> 
> printFrameBufferSize(window, frame++);
> 
> printf("\\n");
> 
> while (!glfwWindowShouldClose(window)) {
> if (frame \< 10) {
> printFrameBufferSize(window, frame++);
> } else {
> glfwSetWindowShouldClose(window, GLFW\_TRUE);// close it
> }
> 
> glfwSwapBuffers(window);
> glfwPollEvents();// \<------- this is the point which changed glfwGetFramebufferSize result
> }
> 
> glfwDestroyWindow(window);
> glfwTerminate();
> return 0;
> }
> \`\`\`\`
> 
> \### The result
> 
> \#### Test CASE 1
> 
> use retina display = false
> poll events before loop = false
> 
> \`\`\`\`shell
> ./main.bin
> frame#-2, fbSize=1280x800, scale=2.00x2.00
> frame#-1, fbSize=1280x800, scale=2.00x2.00
> 
> frame#0, fbSize=1280x800, scale=2.00x2.00
> frame#1, fbSize=640x400, scale=1.00x1.00
> frame#2, fbSize=640x400, scale=1.00x1.00
> frame#3, fbSize=640x400, scale=1.00x1.00
> frame#4, fbSize=640x400, scale=1.00x1.00
> frame#5, fbSize=640x400, scale=1.00x1.00
> frame#6, fbSize=640x400, scale=1.00x1.00
> frame#7, fbSize=640x400, scale=1.00x1.00
> frame#8, fbSize=640x400, scale=1.00x1.00
> frame#9, fbSize=640x400, scale=1.00x1.00
> \`\`\`\`
> 
> \#### Test CASE 2
> 
> use retina display = false
> poll events before loop = true
> 
> \`\`\`\`shell
> ./main.bin poll
> frame#-2, fbSize=1280x800, scale=2.00x2.00
> frame#-1, fbSize=640x400, scale=1.00x1.00
> 
> frame#0, fbSize=640x400, scale=1.00x1.00
> frame#1, fbSize=640x400, scale=1.00x1.00
> frame#2, fbSize=640x400, scale=1.00x1.00
> frame#3, fbSize=640x400, scale=1.00x1.00
> frame#4, fbSize=640x400, scale=1.00x1.00
> frame#5, fbSize=640x400, scale=1.00x1.00
> frame#6, fbSize=640x400, scale=1.00x1.00
> frame#7, fbSize=640x400, scale=1.00x1.00
> frame#8, fbSize=640x400, scale=1.00x1.00
> frame#9, fbSize=640x400, scale=1.00x1.00
> \`\`\`\`
> 
> \#### Test CASE 3
> 
> use retina display = true
> poll events before loop = false
> 
> \`\`\`\`shell
> ./main.bin retina
> frame#-2, fbSize=1280x800, scale=2.00x2.00
> frame#-1, fbSize=1280x800, scale=2.00x2.00
> 
> frame#0, fbSize=1280x800, scale=2.00x2.00
> frame#1, fbSize=1280x800, scale=2.00x2.00
> frame#2, fbSize=1280x800, scale=2.00x2.00
> frame#3, fbSize=1280x800, scale=2.00x2.00
> frame#4, fbSize=1280x800, scale=2.00x2.00
> frame#5, fbSize=1280x800, scale=2.00x2.00
> frame#6, fbSize=1280x800, scale=2.00x2.00
> frame#7, fbSize=1280x800, scale=2.00x2.00
> frame#8, fbSize=1280x800, scale=2.00x2.00
> frame#9, fbSize=1280x800, scale=2.00x2.00
> \`\`\`\`
> 
> \#### Test CASE 4
> 
> use retina display = true
> poll events before loop = true
> 
> \`\`\`\`shell
> ./main.bin retina poll
> frame#-2, fbSize=1280x800, scale=2.00x2.00
> frame#-1, fbSize=1280x800, scale=2.00x2.00
> 
> frame#0, fbSize=1280x800, scale=2.00x2.00
> frame#1, fbSize=1280x800, scale=2.00x2.00
> frame#2, fbSize=1280x800, scale=2.00x2.00
> frame#3, fbSize=1280x800, scale=2.00x2.00
> frame#4, fbSize=1280x800, scale=2.00x2.00
> frame#5, fbSize=1280x800, scale=2.00x2.00
> frame#6, fbSize=1280x800, scale=2.00x2.00
> frame#7, fbSize=1280x800, scale=2.00x2.00
> frame#8, fbSize=1280x800, scale=2.00x2.00
> frame#9, fbSize=1280x800, scale=2.00x2.00
> \`\`\`\`

It looks like calling `glfwPollEvents()` before you need to use `glfwGetFramebufferSize` might resolve this.
