{"action":"created","comment":{"url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/comments/42630987","id":42630987,"diff_hunk":"@@ -0,0 +1,127 @@\n+//\n+//  TMProgram.m\n+//  ToneMapper\n+//\n+//  Created by Hagai Weinfeld on 10/8/15.\n+//  Copyright (c) 2015 Lightricks Ltd. All rights reserved.\n+//\n+\n+#import \"TMProgram.h\"\n+\n+#import \"TMMutableHandleDictionary.h\"\n+#import \"TMShaderFactory.h\"\n+#import \"TMShader.h\"\n+\n+NS_ASSUME_NONNULL_BEGIN\n+\n+@interface TMProgram ()\n+\n+/// The handle for the program.\n+@property (nonatomic) GLuint program;\n+\n+/// A \\c TMHandleDictionary that maps attribute names to \\GLuint handles.\n+@property (readwrite, strong, nonatomic) TMHandleDictionary *handlesForAttributes;\n+\n+/// A \\c TMHandleDictionary that maps uniform names to \\GLuint handles.\n+@property (readwrite, strong, nonatomic) TMHandleDictionary *handlesForUniforms;\n+\n+/// The program's vertex shader.\n+@property (strong, nonatomic) TMShader *vertexShader;\n+\n+/// The program's fragment shader.\n+@property (strong, nonatomic) TMShader *fragmentShader;\n+\n+@end\n+\n+@implementation TMProgram\n+\n+#pragma mark -\n+#pragma mark Initialization\n+#pragma mark -\n+\n+- (instancetype)initWithAttributes:(NSArray *)attributes uniforms:(NSArray *)uniforms\n+                  vertexShaderName:(NSString *)vertexShaderName\n+                fragmentShaderName:(NSString *)fragmentShaderName {\n+  if (self = [super init]) {\n+    \n+    TMShaderFactory *shaderFactory = [[TMShaderFactory alloc] init];\n+    \n+    self.vertexShader = [shaderFactory shaderForShaderName:vertexShaderName\n+                                                        shaderType:GL_VERTEX_SHADER];\n+    self.fragmentShader = [shaderFactory shaderForShaderName:fragmentShaderName\n+                                                          shaderType:GL_FRAGMENT_SHADER];\n+    self.program = [self programWithVertexShader:self.vertexShader.handle\n+                                        fragmentShader:self.fragmentShader.handle];\n+    self.handlesForAttributes = [self handleDictionaryFromAttributes:attributes\n+                                                       programHandle:self.program];\n+    self.handlesForUniforms = [self handleDictionaryFromUniforms:uniforms\n+                                                   programHandle:self.program];\n+  }\n+  return self;\n+}\n+\n+- (GLuint)programWithVertexShader:(GLuint)vertexShader\n+                         fragmentShader:(GLuint)fragmentShader {\n+  GLuint program = glCreateProgram();\n+  glAttachShader(program, vertexShader);\n+  glAttachShader(program, fragmentShader);\n+  glLinkProgram(program);\n+  \n+  // Check linkage success.\n+  GLint linkSuccess;\n+  glGetProgramiv(program, GL_LINK_STATUS, &linkSuccess);\n+  if (linkSuccess == GL_FALSE) {\n+    GLchar messages[256];\n+    glGetProgramInfoLog(program, sizeof(messages), 0, &messages[0]);\n+    NSString *messageString = [NSString stringWithUTF8String:messages];\n+    NSLog(@\"Existing, Program link error: %@\", messageString);\n+    exit(1);\n+  }\n+  return program;\n+}\n+\n+- (TMHandleDictionary *)handleDictionaryFromAttributes:(NSArray *)attributes\n+                                         programHandle:(GLuint)program {\n+  TMMutableHandleDictionary *mutableHandlesForAttributes = [[TMMutableHandleDictionary alloc] init];\n+  for (NSString *attribute in attributes) {\n+    GLuint handle = glGetAttribLocation(program, [attribute UTF8String]);\n+    glEnableVertexAttribArray(handle);\n+    [mutableHandlesForAttributes setHandle:handle forKey:attribute];\n+  }\n+  return mutableHandlesForAttributes;\n+}\n+\n+- (TMHandleDictionary *)handleDictionaryFromUniforms:(NSArray *)uniforms\n+                                       programHandle:(GLuint)program {\n+  TMMutableHandleDictionary *mutableHandlesForUniforms = [[TMMutableHandleDictionary alloc] init];\n+  for (NSString *uniform in uniforms) {\n+    GLuint handle = glGetUniformLocation(program, [uniform UTF8String]);","path":"ToneMapper/TMProgram.m","position":98,"original_position":98,"commit_id":"28ce818f2f5391255106b41034b26a8a3d51bc2c","original_commit_id":"28ce818f2f5391255106b41034b26a8a3d51bc2c","user":{"login":"CodeBaseCamp","id":7971250,"avatar_url":"https://avatars.githubusercontent.com/u/7971250?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeBaseCamp","html_url":"https://github.com/CodeBaseCamp","followers_url":"https://api.github.com/users/CodeBaseCamp/followers","following_url":"https://api.github.com/users/CodeBaseCamp/following{/other_user}","gists_url":"https://api.github.com/users/CodeBaseCamp/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeBaseCamp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeBaseCamp/subscriptions","organizations_url":"https://api.github.com/users/CodeBaseCamp/orgs","repos_url":"https://api.github.com/users/CodeBaseCamp/repos","events_url":"https://api.github.com/users/CodeBaseCamp/events{/privacy}","received_events_url":"https://api.github.com/users/CodeBaseCamp/received_events","type":"User","site_admin":false},"body":"same","created_at":"2015-10-21T14:33:31Z","updated_at":"2015-10-21T14:33:31Z","html_url":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4#discussion_r42630987","pull_request_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4","_links":{"self":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/comments/42630987"},"html":{"href":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4#discussion_r42630987"},"pull_request":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4"}}},"pull_request":{"url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4","id":48209442,"html_url":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4","diff_url":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4.diff","patch_url":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4.patch","issue_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/4","number":4,"state":"open","locked":false,"title":"Round 1, Part 1.","user":{"login":"hagaiw","id":13868055,"avatar_url":"https://avatars.githubusercontent.com/u/13868055?v=3","gravatar_id":"","url":"https://api.github.com/users/hagaiw","html_url":"https://github.com/hagaiw","followers_url":"https://api.github.com/users/hagaiw/followers","following_url":"https://api.github.com/users/hagaiw/following{/other_user}","gists_url":"https://api.github.com/users/hagaiw/gists{/gist_id}","starred_url":"https://api.github.com/users/hagaiw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hagaiw/subscriptions","organizations_url":"https://api.github.com/users/hagaiw/orgs","repos_url":"https://api.github.com/users/hagaiw/repos","events_url":"https://api.github.com/users/hagaiw/events{/privacy}","received_events_url":"https://api.github.com/users/hagaiw/received_events","type":"User","site_admin":false},"body":"Round 1. Only some of the \"Leaf\" classes, rest will come in part 2.","created_at":"2015-10-20T14:37:57Z","updated_at":"2015-10-21T14:33:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8a59eef33882c5b3d81344bc10dab461a4f4748d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4/commits","review_comments_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4/comments","review_comment_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/4/comments","statuses_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/statuses/28ce818f2f5391255106b41034b26a8a3d51bc2c","head":{"label":"CodeBaseCamp:pr","ref":"pr","sha":"28ce818f2f5391255106b41034b26a8a3d51bc2c","user":{"login":"CodeBaseCamp","id":7971250,"avatar_url":"https://avatars.githubusercontent.com/u/7971250?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeBaseCamp","html_url":"https://github.com/CodeBaseCamp","followers_url":"https://api.github.com/users/CodeBaseCamp/followers","following_url":"https://api.github.com/users/CodeBaseCamp/following{/other_user}","gists_url":"https://api.github.com/users/CodeBaseCamp/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeBaseCamp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeBaseCamp/subscriptions","organizations_url":"https://api.github.com/users/CodeBaseCamp/orgs","repos_url":"https://api.github.com/users/CodeBaseCamp/repos","events_url":"https://api.github.com/users/CodeBaseCamp/events{/privacy}","received_events_url":"https://api.github.com/users/CodeBaseCamp/received_events","type":"User","site_admin":false},"repo":{"id":42035710,"name":"OpenGLExercise","full_name":"CodeBaseCamp/OpenGLExercise","owner":{"login":"CodeBaseCamp","id":7971250,"avatar_url":"https://avatars.githubusercontent.com/u/7971250?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeBaseCamp","html_url":"https://github.com/CodeBaseCamp","followers_url":"https://api.github.com/users/CodeBaseCamp/followers","following_url":"https://api.github.com/users/CodeBaseCamp/following{/other_user}","gists_url":"https://api.github.com/users/CodeBaseCamp/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeBaseCamp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeBaseCamp/subscriptions","organizations_url":"https://api.github.com/users/CodeBaseCamp/orgs","repos_url":"https://api.github.com/users/CodeBaseCamp/repos","events_url":"https://api.github.com/users/CodeBaseCamp/events{/privacy}","received_events_url":"https://api.github.com/users/CodeBaseCamp/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/CodeBaseCamp/OpenGLExercise","description":"","fork":false,"url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise","forks_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/forks","keys_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/teams","hooks_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/hooks","issue_events_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/events{/number}","events_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/events","assignees_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/assignees{/user}","branches_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/branches{/branch}","tags_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/tags","blobs_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/refs{/sha}","trees_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/statuses/{sha}","languages_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/languages","stargazers_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/stargazers","contributors_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/contributors","subscribers_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/subscribers","subscription_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/subscription","commits_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/commits{/sha}","git_commits_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/commits{/sha}","comments_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/comments{/number}","issue_comment_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/comments{/number}","contents_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/contents/{+path}","compare_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/merges","archive_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/downloads","issues_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues{/number}","pulls_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls{/number}","milestones_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/milestones{/number}","notifications_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/labels{/name}","releases_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/releases{/id}","created_at":"2015-09-07T06:39:12Z","updated_at":"2015-10-19T07:12:39Z","pushed_at":"2015-10-20T14:37:57Z","git_url":"git://github.com/CodeBaseCamp/OpenGLExercise.git","ssh_url":"git@github.com:CodeBaseCamp/OpenGLExercise.git","clone_url":"https://github.com/CodeBaseCamp/OpenGLExercise.git","svn_url":"https://github.com/CodeBaseCamp/OpenGLExercise","homepage":null,"size":404,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"CodeBaseCamp:master","ref":"master","sha":"10f233ed298c0bba0ff022894680af56e0b5b75b","user":{"login":"CodeBaseCamp","id":7971250,"avatar_url":"https://avatars.githubusercontent.com/u/7971250?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeBaseCamp","html_url":"https://github.com/CodeBaseCamp","followers_url":"https://api.github.com/users/CodeBaseCamp/followers","following_url":"https://api.github.com/users/CodeBaseCamp/following{/other_user}","gists_url":"https://api.github.com/users/CodeBaseCamp/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeBaseCamp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeBaseCamp/subscriptions","organizations_url":"https://api.github.com/users/CodeBaseCamp/orgs","repos_url":"https://api.github.com/users/CodeBaseCamp/repos","events_url":"https://api.github.com/users/CodeBaseCamp/events{/privacy}","received_events_url":"https://api.github.com/users/CodeBaseCamp/received_events","type":"User","site_admin":false},"repo":{"id":42035710,"name":"OpenGLExercise","full_name":"CodeBaseCamp/OpenGLExercise","owner":{"login":"CodeBaseCamp","id":7971250,"avatar_url":"https://avatars.githubusercontent.com/u/7971250?v=3","gravatar_id":"","url":"https://api.github.com/users/CodeBaseCamp","html_url":"https://github.com/CodeBaseCamp","followers_url":"https://api.github.com/users/CodeBaseCamp/followers","following_url":"https://api.github.com/users/CodeBaseCamp/following{/other_user}","gists_url":"https://api.github.com/users/CodeBaseCamp/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeBaseCamp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeBaseCamp/subscriptions","organizations_url":"https://api.github.com/users/CodeBaseCamp/orgs","repos_url":"https://api.github.com/users/CodeBaseCamp/repos","events_url":"https://api.github.com/users/CodeBaseCamp/events{/privacy}","received_events_url":"https://api.github.com/users/CodeBaseCamp/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/CodeBaseCamp/OpenGLExercise","description":"","fork":false,"url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise","forks_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/forks","keys_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/teams","hooks_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/hooks","issue_events_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/events{/number}","events_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/events","assignees_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/assignees{/user}","branches_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/branches{/branch}","tags_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/tags","blobs_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/refs{/sha}","trees_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/statuses/{sha}","languages_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/languages","stargazers_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/stargazers","contributors_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/contributors","subscribers_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/subscribers","subscription_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/subscription","commits_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/commits{/sha}","git_commits_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/git/commits{/sha}","comments_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/comments{/number}","issue_comment_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/comments{/number}","contents_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/contents/{+path}","compare_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/merges","archive_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/downloads","issues_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues{/number}","pulls_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls{/number}","milestones_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/milestones{/number}","notifications_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/labels{/name}","releases_url":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/releases{/id}","created_at":"2015-09-07T06:39:12Z","updated_at":"2015-10-19T07:12:39Z","pushed_at":"2015-10-20T14:37:57Z","git_url":"git://github.com/CodeBaseCamp/OpenGLExercise.git","ssh_url":"git@github.com:CodeBaseCamp/OpenGLExercise.git","clone_url":"https://github.com/CodeBaseCamp/OpenGLExercise.git","svn_url":"https://github.com/CodeBaseCamp/OpenGLExercise","homepage":null,"size":404,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4"},"html":{"href":"https://github.com/CodeBaseCamp/OpenGLExercise/pull/4"},"issue":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/4"},"comments":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/CodeBaseCamp/OpenGLExercise/statuses/28ce818f2f5391255106b41034b26a8a3d51bc2c"}}}}